Archived

This topic is now archived and is closed to further replies.

fireking

fault line formation generation method

Recommended Posts

void aperfil_01(float *band, int stride, int icount, float filter)
{
	float v=band[0];
	int j = stride;
	int i;
	for(i=0;i < icount-1;i++)
	{
		band[j]=((filter*v)+((1-filter)*band[j]));
		v=band[j];
		j+=stride;
	}
}
float **fault_formation_f(int width,int height,int low,int high,int iterations,float filter)
{
	float **points=new float*[width];
	for(int i=0;i < width;i++)
	{
		points[ i ]=new float[height];
	}
	for(int ax=0;ax < width;ax++)
	{
		for(int ay=0;ay 0)
	{
		int ttheight=high-((high-low)*iterations)/totiterations;
		int randx1,randy1,randx2,randy2;
		randx1=rangerand(0,width);
		randx2=rangerand(0,width);
		randy1=rangerand(0,height);
		randy2=rangerand(0,height);

		int dirx1,diry1,dirx2,diry2;
		dirx1=randx2-randx1;
		diry1=randy2-randy1;

		for(ix=0;ix < width;ix++)
		{
			for(iy=0;iy < height;iy++)
			{
				dirx2=ix-randx1;
				diry2=iy-randy1;
				if((dirx2*diry1 - dirx1*diry2) > 0)
				{
					points[ix][iy]=ttheight+points[ix][iy];
				}
			}
		}
		iterations--;
	}
	return points;
}
  
basically, the above is an implementation of the fault line formation method of generation terrain. That first function there is the erosion function... Supposedly, after each fault is placed, you're supposed to filter the entire map 4 times, one per direction (north, south, east, west) thats top to bottom, bottom to top, left to right, right to left im not sure on how to do this, i think ive got top to bottom and bottom to top correct, it goes something like aperfil_01(points[ix],1,128,0.4f); aperfil_01(points[width-1-ix],1,128,0.4f); where ix is a number going from 0 to 127, and width is 128 it doesnt like me guys, im telling you, i dont know how to go left to right or right to left... could someone help me who's tried implementing this before? [edited by - fireking on November 15, 2003 8:53:05 AM] [edited by - fireking on November 15, 2003 8:53:45 AM]

Share this post


Link to post
Share on other sites
possibly telling whats wrong could be a great help, not? memory access errors? wrong results? i''ve read carefully your text, not the source as its uncommented anyways (so there is no // <-- crash here anywhere:D).

what shall we do? help you? sure we like to. just tell us your problem.




If that''s not the help you''re after then you''re going to have to explain the problem better than what you have. - joanusdmentia

davepermen.net

Share this post


Link to post
Share on other sites
Like this?



void FilterBand(float *band,int stride,int count,float filter)
{
int i,j=stride;
float v = band[0];
for (i=0;i<count-1;i++)
{
band[j] = (filter*v + (1-filter)*band[j]);
v = band[j];
j+=stride;
}
}

/*
Erosion filter -
Erodes a height field in all 4 directions
*/

void FilterHeightField(float *field,int size,float filter)
{
int i;
/*
Erode rows left to right
*/

for (i=0;i<size;i++)
{
FilterBand(&field[size*i],1,size,filter);
}

/*
Erode rows right to left
*/

for (i=0;i<size;i++)
{
FilterBand(&field[size*i+size-1],-1,size,filter);
}

/*
Erode columns top to bottom
*/

for (i=0;i<size;i++)
{
FilterBand(&field[i],size,size,filter);
}

/*
Erode columns bottom to top
*/

for (i=0;i<size;i++)
{
FilterBand(&field[size*(size-1)+i],-size,size,filter);
}
}


EDIT: Assumes a square height map.
EDIT AGAIN: Change ints to floats.

Josh
vertexnormal AT linuxmail DOT org


Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.

[edited by - VertexNormal on November 17, 2003 8:04:01 PM]

[edited by - VertexNormal on November 17, 2003 8:07:37 PM]

Share this post


Link to post
Share on other sites
@ VertexNormal

The terrain is in the form of a 2 dimensional array...

@ everyone else

the problem is, i dont know how to pass terrain[x][y] into FilterStuff(somepointer,...)

basically, i have a function without the documentation, and since i know erosion is a common topic in terrain generation, i was hoping someone has seen this function somewhere, and would know how to use it...

i need to pass some sort of 1d array to the function, several times, in order to erode the fractal generated terrain...

Share this post


Link to post
Share on other sites
It's basically the same as what I posted, except you have to index the beginning of a band differently, and modify your stride.

Basically, the filter takes a pointer to an array of floats. It knows nothing of how the array is set up, or how the array is indexed. Stride tells it how to increment the current position in the array to get the next position in the band being filtered.

In an array that is indexed such as HeightMap[width][height], then the stride for a row is equal to 1 or -1 (depending on left to right or right to left) and the stride for a column is height or -height (depending on top to bottom or bottom to top). In this case, rows are indexed [ i ][ 0 ] to [ i ][height-1] and columns are indexed [ 0 ][ i ] to [ width-1 ][ i ]. In this context, a row is of length height and is enumerated on the first subscript, while a column is of length width and is enumerated on the second subscript.

(Note: This is why I prefer to index a 2D array like this as HeightMap[ height ][ width ]. That way, the width subscript enumerates columns, and the height subscript enumerates rows; ie, rows are indexed with y and columns are indexed with x. Just a personal preference, but it is the reason for any mistakes in the coming code, as I am having to turn my thinking sideways to think in terms of indexing [ width ][ height ]. So please, forgive me if I made any errors.)

So, to filter all rows from left to right, we need to iterate through all of the rows (0..width), and take the address of the element at the beginning of each row ( [ i ][ 0 ] ). The stride in this case will be +1, as the elements in the row are organized: [ i ][ 0 ], [ i ][ 1 ], [ i ][ 2 ] etc...

for(i=0; i< width; i++)
{
FilterBand((float *)&HeightMap[ i ][ 0 ], 1, height, filter);
}


To filter right to left, we need to take the address of the element at the END of each row(height-1), and apply a stride of -1 (as the elements in this band are ordered [ i ][ height-1 ], [ i ][ height-2 ], etc...).

for(i=0; i< width; i++)
{
FilterBand((float *)&HeightMap[ i ][ height-1 ], -1, height, filter);
}


To filter from top to bottom, we need to iterate on columns (0..height) and take the address at the beginning of each column. In this case, stride will be equal to height (which is the width in sequential elements of each row of your 2D array.) Adding this moves us down a row, to the next element in the band.

for(i=0; i< height; i++)
{
FilterBand((float *)&HeightMap[ 0 ][ i ], height, width, filter);
}


And conversely, filtering from bottom to top we take the address at the end of each column, and a stride of -height.

for(i=0; i< height; i++)
{
FilterBand((float *)&HeightMap[ width-1 ][ i ], -height, width, filter);
}


These snippets should work for your height map. If not, forgive me for any errors.

Good luck, and if you still need help or if I confused you further, don't hesitate to ask.

EDIT: Fix some code mangled by forum/HTML tag interpretation.

Josh
vertexnormal AT linuxmail DOT org


Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.

[edited by - VertexNormal on November 18, 2003 2:41:41 PM]

Share this post


Link to post
Share on other sites
damnit, that doesnt work either...


Unhandled exception at 0x77e73887 in createworld.exe: Microsoft C++ exception: std::bad_alloc @ 0x0012fb58.


im just going to buy the freaking book, thanks for the help anyways...

Share this post


Link to post
Share on other sites
Hmmm... I tested it, and it worked fine. Are you sure the problem isn't somewhere else?

EDIT: Looking more closely at your heightmap generator, it looks like the problem is probably coming from the way you are allocating your height map. You are allocating as an array of separate arrays; the code I posted expects the heightmap to be a single block.

If you want to allocate as an array of arrays, you will have to change the filtering function completely, as you can not expect the arrays to be allocated sequentially. This filtering method (and any algorithm that works with a striding parameter) expects all of the data to be allocated sequentially in memory, rather than as an array of arrays, whose separate arrays could be located just about anywhere.

Modify your heightmap allocation to ensure that the entire map is allocated sequentially in a predictable fashion, and it should work.

Josh
vertexnormal AT linuxmail DOT org


Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.

[edited by - VertexNormal on November 18, 2003 7:37:36 PM]

Share this post


Link to post
Share on other sites
When I chatted with him, I proposed the same thing (after much though.)

I think what might be messing him up is - he''s not declaring a straight 2d array (or a 1d array), he''s creating an array of pointers with an array of pointers inside of them. Because of incontinuity of free memory, perhaps it''s malloc''ing in a non-sequencial way.

I would recommend just mallocing it as a 1d array (and use a little math to treat it as a 2d array)

-Michael

Share this post


Link to post
Share on other sites
Don't mean to jack this thread:

@VertexNormal:
Are you working with terrain stuff right now? Myself and some others are currently (actively) persuing a terrain shadows project. I invite you to check it out:
http://www.gamedev.net/community/forums/topic.asp?topic_id=190453
Let me know if you're interested (via e-mail)

(This is also a test to see if my sig works right)

@Fireking
Check out the above thread if you're interested.

-Michael
[edit: sig test]
-------------------


Current Projects:
|
+-/Heightmap Shadows Calculations
+-/Normal Map->Heightmap Converter
+-/2d Images->3d Object Utility
+-/(future)Simple Terrain Engine w/Collision Detection
+-/(future)Character animation and model loading
:
:
(to be continued)




[edited by - thr33d on November 18, 2003 7:56:46 PM]

Share this post


Link to post
Share on other sites
hey thr33d,

sorry i cause so much confusion sometimes guys...

my array is a 2 dimensional array right? i hope so, otherwise ive been in the dark for about a year...

i finally just said screw his algorithm, and wrote my own, it works decently. its a generic blending function, that adds the pixels around a current pixel, and gets the average, setting the pixel to that value. thats standard blur i guess.

i wrote 4 blurring functions


void blur4(float **points,int width,int height,float s_applyamt,float f_applyamt,int loop)//blurs by 4 points
void blur5(float **points,int width,int height,float s_applyamt,float f_applyamt,int loop)//blurs by 5 points
void blur8(float **points,int width,int height,float s_applyamt,float f_applyamt,int loop)//blurs by 8 points
void blur9(float **points,int width,int height,float s_applyamt,float f_applyamt,int loop)//blurs by 9 points


and i modified all of the terrain generation functions to add more customization, for instance you can specify how each layer is blended together in the fault formation method, instead of just adding the current value...

thank for all the help you''ve guys have given me though, id still be working on my dumb-ass 2d tile engine (that sucked badly) instead of doing 3d stuff, if it werent for this web site and the community on it

thanks

Share this post


Link to post
Share on other sites
Fireking:

While you''re at it, why not just implement a slightly different version of the same function.

Pass in the change in the x and z axis, per iteration. Since you''re working with a 2d array (within the function) and you''re passing the whole array, you should have no problems .

So, this function

void CTERRAIN::FilterHeightBand( float* fpBand, int iStride,
int iCount, float fFilter )

becomes
this function:

void CTERRAIN::FilterHeightBand( float* fpHeightmap[][WIDTH], int ixStride, int izStride,
int iCount, float fFilter )


Don''t forget to pass WIDTH as iCount when moving ixStride -1 or 1, and HEIGHT into iCount when izStride is -1 or 1.

(Looks good from here)
This function should end up "smoothing" the terrain much more than a 3x3 or larger smooth function, when applied to larger terrains (>32x32 I''m guessing)

Go try that,
-Michael

-------------------


Current Projects:
|
+-/Heightmap Shadows Calculations
+-/Normal Map->Heightmap Converter
+-/2d Images->3d Object Utility
+-/(future)Simple Terrain Engine w/Collision Detection
+-/(future)Character animation and model loading
:
:
(to be continued)

Share this post


Link to post
Share on other sites