random hills on surfaces ??

Started by
8 comments, last by arkansas 21 years, 6 months ago
Hey I made a landscape with lots of surfaces. Some of them are like little mountains. I wanna put bumps on there do it looks real. How do I do that? thx arkansas
Advertisement
Do you want to add bumps like in actualy modifying your geometry or just like bumpmap?

You should never let your fears become the boundaries of your dreams.
You should never let your fears become the boundaries of your dreams.
I wanna modify the geometry.

arkansas
So, you want to generate a realistic-looking mountains?
If so, there''s an algorithm lying around somewhere. I''ve seen it before. Too bad I can''t remember the name and it doesn''t appear very often. But such algorithm is exist.
I''ll tell you when I found it.
If you wanna do this procedurally (ie at runtime, and with a certain amount of randomness), then try using a 2D Perlin noise function. Loop through your vertices, calling your noise function with the x and z coords (if your landscape is across the y plane), and deform each point by the amount returned from the function.

For example, try this Perlin noise function (apologies to the author, can''t find the details anyway but I can''t take credit):


  #define PERLIN_SIZE		1024#define PERLIN_RND		((float)(2.0f*(float)rand()/(float)RAND_MAX)-1.0f)#define PERLIN_NORM(X)	{float l = (float)sqrt(X.x*X.x+X.y*X.y);X.x/=l;X.y/=l;}struct Vector2f{	float x, y;};Vector2f perlinField[PERLIN_SIZE][PERLIN_SIZE];void InitPerlinField(int m_scale);void GetPerlinNoiseValue (float x, float y, GLfloat *result);int scale;void InitPerlinField(int m_scale) {	scale = m_scale;	if (scale>128) scale=128;	if (scale<0) scale=0;	for(int y=0; y<PERLIN_SIZE; y++) {		for(int x=0; x<PERLIN_SIZE; x++) {			perlinField[x][y].x = PERLIN_RND;			perlinField[x][y].y = PERLIN_RND;			PERLIN_NORM(perlinField[x][y]);		}	}	for(int i=0; i<scale; i++) {		// Force repeat		perlinField[scale][i] = perlinField[0][i];		perlinField[i][scale] = perlinField[i][0];	}	perlinField[scale][scale] = perlinField[scale][i] = perlinField[i][scale] = perlinField[0][0];}void GetPerlinNoiseValue (float x, float y, GLfloat *result) {	// Scale the input!!	x=(float)((int)(x*PERLIN_SIZE));	y=(float)((int)(y*PERLIN_SIZE));	/* Calculate the index of the list */	int x1, y1, x2, y2;	x1 = (int)x*scale/PERLIN_SIZE;	x2 = x1 + 1;	y1 = (int)y*scale/PERLIN_SIZE;	y2 = y1 + 1;	Vector2f pos;	pos.x = (float)x*(float)scale/(PERLIN_SIZE);	pos.y = (float)y*(float)scale/(PERLIN_SIZE);	/* Calculate the vector from the grid corner to the point */	Vector2f vect[2][2];	vect[0][0].x = pos.x - x1;	vect[0][0].y = pos.y - y1;	vect[0][1].x = pos.x - x1;	vect[0][1].y = pos.y - y2;	vect[1][0].x = pos.x - x2;	vect[1][0].y = pos.y - y1;	vect[1][1].x = pos.x - x2;	vect[1][1].y = pos.y - y2;	float s, t, u, v;	s = perlinField[x1][y1].x*vect[0][0].x + perlinField[x1][y1].y*vect[0][0].y;	t = perlinField[x2][y1].x*vect[1][0].x + perlinField[x2][y1].y*vect[1][0].y;	u = perlinField[x1][y2].x*vect[0][1].x + perlinField[x1][y2].y*vect[0][1].y;	v = perlinField[x2][y2].x*vect[1][1].x + perlinField[x2][y2].y*vect[1][1].y;	float Sx = 3*(pos.x-x1)*(pos.x-x1)-2*(pos.x-x1)*(pos.x-x1)*(pos.x-x1);	float a = s + Sx*(t-s);	float b = u + Sx*(v-u);	float Sy = 3*(pos.y-y1)*(pos.y-y1)-2*(pos.y-y1)*(pos.y-y1)*(pos.y-y1);	*result = a + Sy*(b-a);	*result = (*result)*0.5f+0.5f;}  


And you could use it like this:


  InitPerlinField(4);GLfloat modifier;for (int x=0; x<LANDSCAPE_XSIZE; x++) {	for (int z=0; z<LANDSCAPE_ZSIZE; z++) {		GetPerlinNoiseValue ((float)x, (float)z, &modifier);		// Now you need to deform the point (x, z) on your landscape		// by multiplying the y coord of this point with modifier		// (or you can try adding it).		//		// How you do this depends on how you''re storing your		// landscape verts - buts an example:		landscape[x][z] *= modifier;	}}  


Note that you don''t need to do this every frame! Do it once at the start of your program.

Also, note that for a given input the noise function will always give the same output, so you can use GetPerlinNoiseValue again if you need to determine the height at a given (x, z) on your landscape - for example to find out where to place a character.

HTH...
I.

PS The noise functions take an (x, y) coordinate - but don''t be confused between these and the (x, y) coords in your world; the Perlin''s x and y refer to its internal 2D grid, which you''re mapping onto (x, z).

www.coldcity.com
code, pics, life
[size="2"]www.coldcity.com code, art, life
Hey

thx for all the help. My Idea was almost like the Perlin noise function, but I didn''t have any idea how to relize it.
Now I know how to do it but how do I do it with already deformed surfaces. How can I loop trough vertices of a surface.

big thx

arkansas
When you say already deformed surfaces - are you using a heightmap and want to add a little detail? Or something else?

Can you post some code of your setup routines so I can see how you should loop through your verts?

www.coldcity.com
code, pics, life
[size="2"]www.coldcity.com code, art, life
Ok

I use normal surfaces::

float hill_01[3][3][3] = {
{{-30.0,4.0,10.0},{-60.0,6.0,25.0},{-5.0,2.0,40.0}},
{{-40.0,10.0,10.0},{-60.0,10.0,25.0},{-15.0,2.0,40.0}},
{{-50.0,4.0,10.0},{-50.0,6.0,25.0},{-50.0,2.0,40.0}}
};

U can do alot of neat things with that but without bumps it just doesn''t look real

arkansas

Ah, I see. First you''re going to need lots more polys!

Try making a grid of 50x50 or so...


  GLfloat hill_01[50][50][3];GLfloat height;InitPerlinField(4);for (int i=0; i<50; i++) {  for (int j=0; j<50; j++) {    GetPerlinNoise(i, j, &height);     hill_01[i][j][0] = (float)i-25.0f;   // x coord    hill_01[i][j][1] = height;           // y coord    hill_01[i][j][2] = (float)j-25.0f;   // z coord  }}  
[size="2"]www.coldcity.com code, art, life
BIG THX dude

I got it now.

arkansas

This topic is closed to new replies.

Advertisement