Archived

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

fireking

making terrain's connect together

Recommended Posts

ok, ive reached my end! ive got a terrain, here''s the process huge ass map was created, its 256 blocks of 256x256 arranged in a square (128 blocks by 128 blocks, each 256x256pixels). Each block is then taken into photoshop, resized to 1024x1024, and saved as a .raw file. That .raw file is then loaded into the application, and rendered 10''s bigger (glScalef(10,10,10)). Alright, everything is great, except the maps dont want to connect together exactley right. I know each image lines up EXACTLEY cuz it was compiled in a HUGE map then cut up. why dont the terrains line up in the program? Is it because we''re guestimating by using a step size of 16, and that very slight short cut is making it so that they dont line up? if so, whats a really inexpensive way of conneting terrains... also, for future question i know i will have, how could i dynamically load and unload terrains as the player is walking around, i cant render 256 10240x10240 terrains all at once i also plan on adding dynamic dynamic detail textures (double dynamic intended). Im not sure how i will do this, but i want to, visually, have the detail texture decrease in detail as landscape moves farther from the camera, so that it doesnt appear so (plain). Yes less detail, farther away, will make it look better cuz its scaled across the terrain less, and from far away that looks better.

Share this post


Link to post
Share on other sites
When you cut the large image apart, did you overlap the border? Let''s just say for now that you are cutting the image into 2 halves. It seems to me that there needs to be a row of pixels that both halves share in order to get a smooth transition between one terrain section to the other. Otherwise you''ll be missing a strip between each section or it might appear to take a jump instead of lining up smoothly. If that''s not clear, let me know and I''ll try to explain what I mean more clearly.

Share this post


Link to post
Share on other sites
hey mr. grinch...

i decided to do some more work with this quesiton, and now ill post some images of what im talking about

just for ya info, i used photoshop to do everything, and im cutting the image up into slices, so that every block is exactley 256 x 256

Here is a link to the entire image, beware, its quite large...

entire world image, in low quality jpeg format

Here is images 85,86,and 101. They connect together like so:



here are the images





im am pretty sure that these should line up exactley!

also, if you dont mind, please explain in better detail what you were talking about, and thanks!

Share this post


Link to post
Share on other sites
hey ostol, im not sure what each pixel represents, but if i show you my rendering routine, im sure you can figure that out... im guessing each pixel determines one of the verticies


int ix;
int iz;
for(iz=0;iz < MAP_SIZE-1;iz+= STEP_SIZE)
{
glBegin(GL_TRIANGLE_STRIP);
for(ix=0;ix < MAP_SIZE-1;ix+= STEP_SIZE)
{
SetTextureCoord((float)ix,(float)iz);
glNormal3f((float)ix,(float)Height(pHeightMap,ix,iz),iz);
//glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(ix,Height(pHeightMap,ix,iz),iz);
SetTextureCoord((float)ix,(float)iz+STEP_SIZE);
glNormal3f((float)ix,(float)Height(pHeightMap,ix,iz+STEP_SIZE),iz+STEP_SIZE);
//glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(ix,Height(pHeightMap,ix,iz+STEP_SIZE),iz+STEP_SIZE);
}
glEnd();
}


the Height() function returns the current value (we use it as y) at that location (specified by x,z) in the array of the .raw file.

[edited by - fireking on October 20, 2003 9:21:50 PM]

[edited by - fireking on October 20, 2003 9:22:47 PM]

Share this post


Link to post
Share on other sites
i think wat mr grinch meant is this.. take the following grid for example:


. . x .
. . x .
. . x .
. . x .


assume all points (x or .) are pixels on the raw image. if u cut the image along ''x'' u will have two images like the following:


(1) (2)
. . x .
. . x .
. . x .
. . x .


now THAT is a bit wrong to store them coz the columns 1 and 2 are two diff values but they represetn edges of a sub-grid. what they SHUD look like is as follows (i think):


. . x x .
. . x x .
. . x x .
. . x x .


the images shud have one common column so that the rendered vertices coincide.

another note, do NOT resize the images AFTER splitting them up unless u use nearest neighbour filtering in photoshop. Any other filters will cause slight mismatch in the value on the edges of adjacent grids. BUT even using nearest neighbour, u''re overall grid might end up looking rough. Think about it.

Share this post


Link to post
Share on other sites
im hoping the nearest neighbor thing works...

i do not want to end up programming some sort of (fill in the gaps) algorithm, cuz thats just too costly and really a cop out job... i want the terrains to fit together without hassle.

Share this post


Link to post
Share on other sites
I think the other responders got what I was saying, but I'll try to illustrate it a bit here. For this example, I'm just going to talk about a 1D array, but it works the same for 2D. Ok, let's say you have an array of floats for the heightmap:

float heightmap[4]; // Small terrain for this example

Ok, now let's say the values of those array elements are:
{1.0, 2.0, 3.0, 4.0}

Picture it as a steadily increasing terrain (height goes from 1 to 4). Ok, so now you split that into 2 terrain sections right down the middle. When you draw the sections, you draw polygons (triangles, quads, whatever you do) between 1.0-2.0 in your first section of terrain. Then, your next section of terrain draws the polygons between 3.0-4.0. However, when you split it, you basically lost the drawing between 2.0-3.0.

So my suggestion is to re-split your image so that each section shares it's borders with the sections around it. In the example above, instead of making two sections of 1-2 and 3-4, you would make two of 1-2 and 2-4. That way when you draw your sections, you draw 1.0-2.0 in your first section, and 2.0-3.0-4.0 in your next section, given you a smooth border. I expect that may get a little more complicated if you add LOD, but it should be pretty similar to other crack fixes. Is that more helpful? I'm afraid this didn't come out as clearly as I hoped, so let me know if I can explain something more clearly.

One more thing: if you stuck the 1-2 and 3-4 sections together, they would seem to make a complete image. However, when drawing vertices of the heightmaps, remember that it is the polygons between the vertices that make it seem continuous. The sections need shared vertices.

[edited by - Mr Grinch on October 20, 2003 11:10:17 PM]

Share this post


Link to post
Share on other sites
i understand what your talking about, but how to i split my images so that they share a border? this is a huge map, so whatever process would hopefully be batchable (new word of the day) cuz whatever that process is, i have to do it 256 times...

Share this post


Link to post
Share on other sites
i just got an idea, would there be a simple algorithm i could write that would modify the height values after loading them into the application, this way i could just find the average between each landscape''s neighbor, and they would connect together?

this seems like a more plausible solution to what im trying to accomplish, but i dont know where to start on writing that algorithm

Share this post


Link to post
Share on other sites
well i started on the algorithm, but it doesnt set the height on the right part of the terrain, im not sure how to set a specific part of a 1d array...


void AverageNeighbor(BYTE *pHeightMap,BYTE *pHeightMap2,int type)//0=h1 is south of h2;1=h1 is east of h2;
{
int ix,iz,hm1hv,hm2hv,fv;;
switch(type)
{
case 0:
for(ix=0;ix < MAP_SIZE-1;ix++)
{
hm1hv=Height(pHeightMap,ix,0);
hm2hv=Height(pHeightMap2,ix,MAP_SIZE-1);
fv=(hm1hv+hm2hv)/2;
//pHeightMap[ix]=fv;
//pHeightMap2[ix*(MAP_SIZE-1)]=fv;
pHeightMap[ix]=0;
pHeightMap2[ix*(MAP_SIZE-1)]=0;
}
break;
case 1:
for(iz=0;iz < MAP_SIZE-1;iz++)
{
hm1hv=Height(pHeightMap,0,iz);
hm2hv=Height(pHeightMap2,MAP_SIZE-1,iz);
fv=(hm1hv+hm2hv)/2;
//pHeightMap[iz]=fv;
//pHeightMap2[iz*(MAP_SIZE-1)]=fv;
pHeightMap[iz]=0;
pHeightMap2[iz*(MAP_SIZE-1)]=0;
}
break;
}
}


this baby will work as soon as someone can help me figure out how to set a value at a specific location in the array only by knowing x and z

[edited by - fireking on October 20, 2003 12:58:47 AM]

Share this post


Link to post
Share on other sites
Ok, let's say you have a 3x3 heightmap stored in a 1D array, it gets stored something like this:
0 1 2
3 4 5
6 7 8

Basically, (0, 0) is heightmap[0], (1, 0) is heightmap[1], (2, 2) is heightmap[8], etc.

Ok, here's the idea:
(z*width)+x

where width is the width of the terrain (3 in the example). So to get (1, 2), it is (2*3)+1 = 7. That's good, because (1, 2) = 7 in my example array at the top, too. Hope that helps.


Ok, I realized that this method works great for how I load in and store my heightmap data, but it may not be how you store your data. Hopefully, this at least gives you an idea how to approach it.

[edited by - Mr Grinch on October 21, 2003 1:29:11 AM]

Share this post


Link to post
Share on other sites
WOO HOO!!!

I DID IT!!!!!!!!!!!!!!!!!!!!!!

I CONNECTED 3 TERRAINS TOGETHER SEEMLESSLY!!!!!!!! I AM THE MAN!!!!!

oh.... well i couldnt have done it without you guys, of course ...


thanks!

source code!!


//rendering the terrain, using step size for triangle resolution
int ix;
int iz;
for(iz=0;iz < MAP_SIZE-STEP_SIZE;iz+= STEP_SIZE)
{
glBegin(GL_TRIANGLE_STRIP);
for(ix=0;ix < MAP_SIZE;ix+= STEP_SIZE)
{
SetTextureCoord((float)ix,(float)iz);
glNormal3f((float)ix,(float)Height(pHeightMap,ix,iz),iz);
//glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(ix,Height(pHeightMap,ix,iz),iz);
SetTextureCoord((float)ix,(float)iz+STEP_SIZE);
glNormal3f((float)ix,(float)Height(pHeightMap,ix,iz+STEP_SIZE),iz+STEP_SIZE);
//glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(ix,Height(pHeightMap,ix,iz+STEP_SIZE),iz+STEP_SIZE);
}
glEnd();
}

//averaging points between neighbors
int GetPos(int x,int z)
{
return (z*MAP_SIZE)+x;
}
void AverageNeighbor(BYTE *pHeightMap,BYTE *pHeightMap2,int type)//0=h1 is south of h2;1=h1 is east of h2;
{
int ix,iz,hm1hv,hm2hv,fv;;
switch(type)
{
case 0:
for(ix=0;ix < MAP_SIZE;ix+=STEP_SIZE)
{
hm1hv=Height(pHeightMap,ix,0);
hm2hv=Height(pHeightMap2,ix,MAP_SIZE-STEP_SIZE);
fv=(hm1hv+hm2hv)/2;
pHeightMap[GetPos(ix,0)]=fv;
pHeightMap2[GetPos(ix,MAP_SIZE-STEP_SIZE)]=fv;
}
break;
case 1:
for(iz=0;iz < MAP_SIZE-1;iz+=STEP_SIZE)
{
hm1hv=Height(pHeightMap,0,iz);
hm2hv=Height(pHeightMap2,MAP_SIZE-STEP_SIZE,iz);
fv=(hm1hv+hm2hv)/2;
pHeightMap[GetPos(0,iz)]=fv;
pHeightMap2[GetPos(MAP_SIZE-STEP_SIZE,iz)]=fv;
}
break;
}
}

//retreiving the height point at a specified locaiton (x,z)
int Height(BYTE *pHeightMap,int X,int Y)
{
// Make sure we don't go past our array size
if(X < 0 || X > MAP_SIZE-1) return 0;
if(Y < 0 || Y > MAP_SIZE-1) return 0;
//int x = X % MAP_SIZE; // Error check our x value
//int y = Y % MAP_SIZE; // Error check our y value

if(!pHeightMap) return 0; // Make sure our data is valid

// Use the equation: index = (x + (y * arrayWidth) ) to find the current height
return pHeightMap[X+(Y*MAP_SIZE)]; // Index into our height array and return the height
}

//frame routine
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //camera routine

glScalef(10,10,10);
RenderHeightMap(g_HeightMap,0);
glTranslatef(1024.0f-STEP_SIZE,0.0f,0.0f);
RenderHeightMap(g_HeightMap2,2);
glTranslatef(-1024.0f+STEP_SIZE,0.0f,1024.0f-STEP_SIZE);
RenderHeightMap(g_HeightMap3,3);
glScalef(-10,-10,-10);
SwapBuffers(g_hDC);


i hope this helps somebody that's in my place in the future, this was stressful (might miss some work over this, from staying up too late) and very fun at the same time. Terrains = fun..

have a good day, and thanks to all that helped!

last but not least, a little screen shot

Classic Before and After:



the only break you see is the differences in colors between the two textures, cuz im no texture artist, i can assure you that the edges are definately connected together

[edited by - fireking on October 21, 2003 1:59:25 PM]

Share this post


Link to post
Share on other sites