Hexagonal landscape :?:
Hexagonal landscape :?:
I want to use a hexagonal landscape, like in typical turn based strategic games (i.e. "Battle Isle" series or "Battle For Wesnoth") but in 3D.
But it sems to me Irrlicht is just supporting traditional rectangular heightfields, am I right?
Is there any way to use a hexagonal landscapes or have I to write a new SceneNode? And, by the way, what is the best way to do this? I am thinking about a mesh. Additionally the landscap eshould be covered by textures using blending.
Or has someone out there just implemented one?
Thanks for your information.
It would be possible to produce a hexagon grid on top of the rectangular terrain. That way you could use the one rectangular terrrain for the map (or more depending on how big your terrain needs to be) and then use the overlayed grid to determine the movement of the units on the grid. It is not necessary to make every hexagon of the map a seperate mesh.
you may want to check out
http://www.eve-corp.com/2080/downloads.html
it's got most of your isometric stuff in it already for you. He uses a mesh for every tile, with no hightmapping, but it really wouldn't be all that hard to write your own scene node.
http://www.eve-corp.com/2080/downloads.html
it's got most of your isometric stuff in it already for you. He uses a mesh for every tile, with no hightmapping, but it really wouldn't be all that hard to write your own scene node.
@guest1:
Well, I am not sure, but, is there any hexagonal grid to be seen?
@Masdus:
But, there will be information which is going to be losed, right?
Actual ideas to map a hexagonal landscape to a rectangular are going these ways:
(not very smooth painting, okay )
You can see the hexagonal grid and the rectangular one, I hope...
the red dots are common shared points. no problem to convert. the green ones have to be computed (i.e. by interpolation). simple, too.
You can see that the distances between the lines are unequally. That is a problem.
Another way of mapping looks like this:
It's more the way I would simply do it, because the hex contains information of its height "in the centre". But you can notice a false aspect ratio.
BUT, how to handle the false aspect ratio?
Or is there another way to map the edges?
Or am I just stupid?
Well, I am not sure, but, is there any hexagonal grid to be seen?
@Masdus:
But, there will be information which is going to be losed, right?
Actual ideas to map a hexagonal landscape to a rectangular are going these ways:
(not very smooth painting, okay )
You can see the hexagonal grid and the rectangular one, I hope...
the red dots are common shared points. no problem to convert. the green ones have to be computed (i.e. by interpolation). simple, too.
You can see that the distances between the lines are unequally. That is a problem.
Another way of mapping looks like this:
It's more the way I would simply do it, because the hex contains information of its height "in the centre". But you can notice a false aspect ratio.
BUT, how to handle the false aspect ratio?
Or is there another way to map the edges?
Or am I just stupid?
ah... yes, you would be best off with the creating of your own scene node. I might suggest using 6 triangles to achieve that effect (or a fan if you know how to do those)
I recommended you to a isometric diamond grid engine, but you should be able to simply replace most of the code with your hex grids...
At one point in my life I wrote the second image you displayed in OpenGL. It was very easy. I wouldn't worry too much about the scene node... it's going to be very simple... your hardest part (which I didn't do) will be UV coords. You're going to need to know if you're going to spread a texture across a bunch of those grids or every one of them individually.
aight man, good luck
I recommended you to a isometric diamond grid engine, but you should be able to simply replace most of the code with your hex grids...
At one point in my life I wrote the second image you displayed in OpenGL. It was very easy. I wouldn't worry too much about the scene node... it's going to be very simple... your hardest part (which I didn't do) will be UV coords. You're going to need to know if you're going to spread a texture across a bunch of those grids or every one of them individually.
aight man, good luck
oh whoops.
I misdirected you slightly. I might make a suggestion: Looking at your second image, you will want to make the RED vertexes aligned to the greyscale heightmap information, and the GREEN vertexes don't exist... they are calculated.
To make something like that, it's very simple. Here is some pseudo-code (kinda C++ syntax) DO NOT USE THIS CODE -- I'M NOT RESPONSIBLE FOR BUGS (or otherwise bad coding in general)!!!!
c8 height[256][256]; // this is your heightmap image
f32 total_width = 64.0; // this is the width of the grid
f32 total_height = 48.0; // this is the height of the whole grid
f32 x_inc = (256*3 + 2) / total_width; // there are 3x+2 increments
f32 y_inc = (256 + 2) / total_height; // there x+2 increments (height)
f32 x = 0;
f32 y = 0;
f32 z = 0;
s32 i, j;
bool even = true;
vector3df<f32> grid[256][256][7]; // 7 vertexes per hex
//this will place all the vertexes
for(i = 0; i<256; i++)
{
x = 0.0;
y = (2*y_inc) * i;
for(j = 0; j<256; j++)
{
z = height[j] / 255.0; // store height -- we'll fix this later
// (center)
grid[j][0].X = x+(x_inc*2);
grid[j][0].Y = y+y_inc;
grid[j][0].Z = z;
// (far left)
grid[j][1].X = x;
grid[j][1].Y = y+y_inc;
grid[j][1].Z = z;
// (left bottom)
grid[j][2].X = x+x_inc;
grid[j][2].Y = y;
grid[j][2].Z = z;
// (right bottom)
grid[i][j][3].X = x+(x_inc*3);
grid[i][j][3].Y = y;
grid[i][j][3].Z = z;
// (far right)
grid[i][j][4].X = x+(x_inc*4);
grid[i][j][4].Y = y+y_inc;
grid[i][j][4].Z = z;
// (right top)
grid[i][j][5].X = x+(x_inc*3);
grid[i][j][5].Y = y+(y_inc*2);
grid[i][j][5].Z = z;
// (left top)
grid[i][j][6].X = x+x_inc;
grid[i][j][6].Y = y+(y_inc*2);
grid[i][j][6].Z = z;
if(even)
{
x += 3*x_inc;
y += y_inc;
}
else
{
x += 3*x_inc;
y -= y_inc;
}
}
}
//this will interpolate the horizontal verts (I hope)
for(i = 0; i<256; i++)
{
for(j = 0; j<256-2; j++)
{
x = grid[i][j][0].Z;
y = grid[i][j+2][0].Z;
z = (x-z) / 3;
grid[i][j][4] = z // far right
grid[i][j+1][2] = z // bottom left
grid[i][j+1][3] = z*2 // bottom right
grid[i][j+2][1] = z*2 // far left
}
}
//this will interpolate the missed verts (I think)
for(i = 0; i<256-2; i++)
{
x = grid[i][0][0].Z; // center
y = grid[i][1][6].Z; // top left
z = (x-z) / 2;
grid[i][0][5] = z // top right
grid[i][1][1] = z // far left
}
-----------------------
That should be it (I'm porting old OpenGL asm code here), You will then probably want to do another loop that merges all duplicate vertices, then another loop that creates the indices. That's beyond the scope of my message though
peace
P.S. I'm writing the code off of the top of my head. There's probably a very good chance that it's broken, so just use it for reference
I misdirected you slightly. I might make a suggestion: Looking at your second image, you will want to make the RED vertexes aligned to the greyscale heightmap information, and the GREEN vertexes don't exist... they are calculated.
To make something like that, it's very simple. Here is some pseudo-code (kinda C++ syntax) DO NOT USE THIS CODE -- I'M NOT RESPONSIBLE FOR BUGS (or otherwise bad coding in general)!!!!
c8 height[256][256]; // this is your heightmap image
f32 total_width = 64.0; // this is the width of the grid
f32 total_height = 48.0; // this is the height of the whole grid
f32 x_inc = (256*3 + 2) / total_width; // there are 3x+2 increments
f32 y_inc = (256 + 2) / total_height; // there x+2 increments (height)
f32 x = 0;
f32 y = 0;
f32 z = 0;
s32 i, j;
bool even = true;
vector3df<f32> grid[256][256][7]; // 7 vertexes per hex
//this will place all the vertexes
for(i = 0; i<256; i++)
{
x = 0.0;
y = (2*y_inc) * i;
for(j = 0; j<256; j++)
{
z = height[j] / 255.0; // store height -- we'll fix this later
// (center)
grid[j][0].X = x+(x_inc*2);
grid[j][0].Y = y+y_inc;
grid[j][0].Z = z;
// (far left)
grid[j][1].X = x;
grid[j][1].Y = y+y_inc;
grid[j][1].Z = z;
// (left bottom)
grid[j][2].X = x+x_inc;
grid[j][2].Y = y;
grid[j][2].Z = z;
// (right bottom)
grid[i][j][3].X = x+(x_inc*3);
grid[i][j][3].Y = y;
grid[i][j][3].Z = z;
// (far right)
grid[i][j][4].X = x+(x_inc*4);
grid[i][j][4].Y = y+y_inc;
grid[i][j][4].Z = z;
// (right top)
grid[i][j][5].X = x+(x_inc*3);
grid[i][j][5].Y = y+(y_inc*2);
grid[i][j][5].Z = z;
// (left top)
grid[i][j][6].X = x+x_inc;
grid[i][j][6].Y = y+(y_inc*2);
grid[i][j][6].Z = z;
if(even)
{
x += 3*x_inc;
y += y_inc;
}
else
{
x += 3*x_inc;
y -= y_inc;
}
}
}
//this will interpolate the horizontal verts (I hope)
for(i = 0; i<256; i++)
{
for(j = 0; j<256-2; j++)
{
x = grid[i][j][0].Z;
y = grid[i][j+2][0].Z;
z = (x-z) / 3;
grid[i][j][4] = z // far right
grid[i][j+1][2] = z // bottom left
grid[i][j+1][3] = z*2 // bottom right
grid[i][j+2][1] = z*2 // far left
}
}
//this will interpolate the missed verts (I think)
for(i = 0; i<256-2; i++)
{
x = grid[i][0][0].Z; // center
y = grid[i][1][6].Z; // top left
z = (x-z) / 2;
grid[i][0][5] = z // top right
grid[i][1][1] = z // far left
}
-----------------------
That should be it (I'm porting old OpenGL asm code here), You will then probably want to do another loop that merges all duplicate vertices, then another loop that creates the indices. That's beyond the scope of my message though
peace
P.S. I'm writing the code off of the top of my head. There's probably a very good chance that it's broken, so just use it for reference
I have still coded a Node which uses triangle fans for each hex. it's nice, because it repsects the correct aspect ratio. And even on my old 550MHz (GeForce4 MX 440 AGB8x) I get nearly 40 fps
But, the landscape is not smoothened (no bezier functionality, actually).
And the landscape uses different textures for each hex (or it could....), but they do not blend into each other.
Here you can see some screenshots (the six at the bottom of the page):
http://tiglis.sourceforge.net/screenshots/
The other way, to lay a rectangular landscape over a hexagonal one is not working (looking!) as I wished. I should make a screenshot, too, to show the differences in aspect ratio...
But, the landscape is not smoothened (no bezier functionality, actually).
And the landscape uses different textures for each hex (or it could....), but they do not blend into each other.
Here you can see some screenshots (the six at the bottom of the page):
http://tiglis.sourceforge.net/screenshots/
The other way, to lay a rectangular landscape over a hexagonal one is not working (looking!) as I wished. I should make a screenshot, too, to show the differences in aspect ratio...
it shouldn't be too hard to get UV coords on to your meshes. If you paste your hex scenenode code, I can point out how to get a UV coord out of it (so you can map a detail texture on top of a "global" texture. of course, if it's stretched over a few textures, you're going to need to implement some fancy texture splitting (like in the terrain scene node)
BTW, your project's lookin good!
BTW, your project's lookin good!
Well, currently my code for a SceneNode is not functional due to code workings I hope i have enough time to fix it, soon!
On the other hand you can take a look at an "engine free" (pure OpenGL on top of SDL) code, since the SceneNode code depends heavily on it! But don't expect surprising code - it's just a proof of concept. Main work is done in TerrainEngine.cpp: http://tiglis.sundawn.net/terrain.tar.bz2
On the other hand you can take a look at an "engine free" (pure OpenGL on top of SDL) code, since the SceneNode code depends heavily on it! But don't expect surprising code - it's just a proof of concept. Main work is done in TerrainEngine.cpp: http://tiglis.sundawn.net/terrain.tar.bz2
one of my first OGL programs displayed a 3D hex terrain from a 2D grid of height (or Z-axis) values
Firstly, all you have to imagine is that each point is a hex, but that each Column is staggered:
Secondly, you cannot simply draw a Hex at each point-- because then you'd have a bunch of floating hexes with nothing connecting them. You have to draw rectangles that connect each hex side with the surrounding hex sides.
You could do this with verticle-only rects, but I found its more pleasing if you do the following: 1) only draw a hex that is 80% of the size of the hex's actual area, 2) draw a rectangle that goes from your smaller hex sides to the adjacent hexs' smaller hex sides.. this gives everything a nice sloped look.
Such a thing took me a week to do, and I was a beginning programmer at the time. I'd give an average programmer 2 days.
Firstly, all you have to imagine is that each point is a hex, but that each Column is staggered:
Code: Select all
[0,0] [0,2]
[0,1] [0,3]
[1,0] [1,2]
[1,1] [1,3]
[2,0] [2,2]
[2,1] [2,3]
You could do this with verticle-only rects, but I found its more pleasing if you do the following: 1) only draw a hex that is 80% of the size of the hex's actual area, 2) draw a rectangle that goes from your smaller hex sides to the adjacent hexs' smaller hex sides.. this gives everything a nice sloped look.
Such a thing took me a week to do, and I was a beginning programmer at the time. I'd give an average programmer 2 days.
a screen cap is worth 0x100000 DWORDS
@keless:
Truely, this is possible to do. But it is very hard to find correct textures and smoothening the world by beziere will be nearly impossible, I think. Hope, I have understood your method correctly.... (stretch the hexes away from each other and connect them by additional rectangles and triangles)
Truely, this is possible to do. But it is very hard to find correct textures and smoothening the world by beziere will be nearly impossible, I think. Hope, I have understood your method correctly.... (stretch the hexes away from each other and connect them by additional rectangles and triangles)
it definately would be hard to smooth.
I personally was going for a look that reflected terrain, but also captured the blocky feel of actual hexagons, so this was okay for me.
I hadnt got around to texturing, but it would be pretty simple, thru the same methods that are used for texturing any height map, with just a little tweaking for the offset columns.
I personally was going for a look that reflected terrain, but also captured the blocky feel of actual hexagons, so this was okay for me.
I hadnt got around to texturing, but it would be pretty simple, thru the same methods that are used for texturing any height map, with just a little tweaking for the offset columns.
a screen cap is worth 0x100000 DWORDS