Making Smooth Terrain (Heightmap with cos curve)

프로그래밍/3D프로그래밍 2008/03/07 03:26

Making Smooth Terrain (Heightmap with cos curve)
by EuiBeom Hwang 2006 (English translation 2008.3)
blog : http://xevious7.com

link: first version (in korean) http://www.xevious7.com/107
(이 문서의 한국어 최초버전 2006년판)

This is for Heightmap Editing Technique. There are many techniques to making terrain,like as perlin noise,  fractals ,and height map and so on.

but If you like to edit manually  your own terrain especially height map matrix.
I hope this document may be helpful

Algorithms

It's simple algorithsm but I think it's powerful for creating smooth mountain thing.
( terrain vertex data ).

first of all I assume you have n x n height vertex matrix. then,

1. choose one vertex ,(for example (10,10)) this vertex will be top of moutain thing.

2. set height .(for example , height = 7)

3. get a expanding factor ( this mean how many vertex are influenced by cos curve)

factor value is lager as base height value is higer  and we can adjust this factor with ratio constant.

expanding_count = baseheight / ratio

if ratio is smaller the curve is definitely smooth form , or ratio is bigger the curve
is more sharp. see the picture 4. get cosine curve value each vertex. and set that value.

5. recursive step 1-4 to next vertex with calculated cosine curve value

Simple implementation C code.
(it's just algorithms implementation code ,no optimization  )
assume , you have  xsize * ysize height vertex data.
GetHeightValue( x,z) function get height of x,z coordination
also SetHeightValue(x,z,value) yep. it's name meaning that's it.

HChangeCosOrg(int x,int z)
{

float baseHeight = GetHeightValue(int x,int z) ;
float ratio = 1.3f;
int iBase;
float delta,sum=0.0f;
float c_value = 0.0f;

iBase = (int) (baseHeight / ratio) ;
// ratio > 0.0f , width value smaller , slope more smooth.

if(iBase < 2 ) return true; // no work if expand factor is smaller than 2
delta =  180.0f / iBase;

for(int i=1 ; i < iBase ; i++)
{
sum += delta;
if(sum > 180.0f) break;

c_value =( baseHeight * ((cos( (sum * 3.141592)/180.0f) + 1.0f) / 2.0f));

// next two vertext(right,left) value setting
if( (((x+i) % sizex) + i) < sizex ) { // check right boundary.

if(c_value > GetHeightValue(x+i,z) ) SetHeightValue(x+i,z,c_value);
}

if( (((x-i) % sizex )- i) > 0 ) { // check left boundary

if(c_value > GetHeightValue(x-i,z) ) SetHeightValue(x-i,z,c_value);
}

// up down recursion
if( ((z-i) % sizez) < (sizez) ) {
if(c_value > GetHeightValue(x,z-i) ) SetHeightValue(x,z-i,c_value);
HChangeCosOrg_SUB(x,z);
}
if( ((z+i) % sizez) < (sizez) ) {
if(c_value > GetHeightValue(x,z-i) ) SetHeightValue(x,z-i,c_value);
HChangeCosOrg_SUB(x,z);
}
}

}

HChangeCosOrg_SUB(int x,int z) // same above except up down expand.
{                                               // it's for no redundant recursion.

float baseHeight = GetHeightValue(int x,int z) ;
float ratio = 1.3f;
int iBase;
float delta,sum=0.0f;
float c_value = 0.0f;

iBase = (int) (baseHeight / ratio) ;
// ratio > 0.0f , width value smaller , slope more smooth.

if(iBase < 2 ) return true; // no work if expand factor is smaller than 2
delta =  180.0f / iBase;

for(int i=1 ; i < iBase ; i++)
{
sum += delta;
if(sum > 180.0f) break;

c_value =( baseHeight * ((cos( (sum * 3.141592)/180.0f) + 1.0f) / 2.0f));

// next two vertext(right,left) value setting
if( (((x+i) % sizex) + i) < sizex ) { // check right boundary.

if(c_value > GetHeightValue(x+i,z) ) SetHeightValue(x+i,z,c_value);
}

if( (((x-i) % sizex )- i) > 0 ) { // check left boundary

if(c_value > GetHeightValue(x-i,z) ) SetHeightValue(x-i,z,c_value);
}

}
}

result screenshot Further thinking

more smooth

If you using variant expanding factor( step 3 in algorithsm) , you will get more smooth moutain thing.

random map

If you want to automatically generating random terrain map with this technique , it's simple make height of top using random function and looping will make random cos curve terrain map.

If you want another random map technique ,see following link.

http://freespace.virgin.net/hugo.elias/models/m_perlin.htm