 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Paul Nicholls Guest
|
Posted: Thu Jun 10, 2004 2:32 am Post subject: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Hi all, I am interested in finding out the approximate slope at any x,z
point in a Byte filled heightmap...
I am at the moment creating each pixel in the heightmap texture array
depending on the height range, but I now want to add in that if the slope is
too steep for some terrain types then I will use rock for example instead.
So I need to find out the slope at any x,z point...
Does anyone have a small code snipit that can help me?
Thanks in advance,
Paul Nicholls (Delphi 5/6 Professional)
"The plastic veneer of civilization is easily melted in the heat of the
moment" - Paul Nicholls
[email]paul-nicholls (AT) hotmail (DOT) com[/email]
Replace '-' with '_' to reply
|
|
| Back to top |
|
 |
Lord Crc Guest
|
Posted: Thu Jun 10, 2004 3:02 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
On Thu, 10 Jun 2004 12:32:35 +1000, "Paul Nicholls" <.> wrote:
| Quote: | So I need to find out the slope at any x,z point...
|
normalX = hmap[x+1, z] - hmap[x-1, z];
normalZ = hmap[x, z+1] - hmap[x, z-1];
simplest is to set normalY = 1 and normalize, and use this normal
- Asbjørn
|
|
| Back to top |
|
 |
Paul Nicholls Guest
|
Posted: Thu Jun 10, 2004 3:15 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Thanks Asbjorn
I'll try this...
Cheers,
Paul.
"Lord Crc" <lordcrc (AT) hotmail (DOT) com> wrote
| Quote: | On Thu, 10 Jun 2004 12:32:35 +1000, "Paul Nicholls" <.> wrote:
So I need to find out the slope at any x,z point...
normalX = hmap[x+1, z] - hmap[x-1, z];
normalZ = hmap[x, z+1] - hmap[x, z-1];
simplest is to set normalY = 1 and normalize, and use this normal
- Asbjørn
|
|
|
| Back to top |
|
 |
Sean Guest
|
Posted: Thu Jun 10, 2004 3:20 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
"Paul Nicholls" <.> wrote
| Quote: | Hi all, I am interested in finding out the approximate slope at any x,z
point in a Byte filled heightmap...
I am at the moment creating each pixel in the heightmap texture array
depending on the height range, but I now want to add in that if the slope
is
too steep for some terrain types then I will use rock for example instead.
So I need to find out the slope at any x,z point...
|
For your case:
MaxGrad[i,j] := Max ( Abs(y[i,j]-y[i-1,j]) , Abs(y[i,j]-y[i,j-1]) {,
Abs(y[i,j]-y[i-1,j-1])/1.41) } )
|
|
| Back to top |
|
 |
Lord Crc Guest
|
Posted: Thu Jun 10, 2004 4:46 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
On Thu, 10 Jun 2004 13:15:46 +1000, "Paul Nicholls" <.> wrote:
| Quote: | Thanks Asbjorn
|
Btw, adjust the size of Y to determine how "slopy" you want it. Ie, if
it's 1, then since dX or dZ is 1 max too, you wont get any slope
angles < 45 deg. So you prob want to decrease it.
Here's a small sample of a heightmap "texture" which i made by using
the formulate i stated http://lordcrc.no-ip.com/public/hmap.jpg
Just a quicky i made after writing this post :)
- Asbjørn
|
|
| Back to top |
|
 |
Paul Nicholls Guest
|
Posted: Thu Jun 10, 2004 6:08 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
erm, I'm actually having trouble using the normal from the calculation you
provided so I can blend the two textures...
lets say I have the two texture rgb values like so:
(r1,g1,b1) = snow (for example)
(r2,g2,b2) = rock (for example)
t = 0..1 (how to calculate)
r := (1-t) * r1 + t * r2;
g := (1-t) * g1 + t * g2;
b := (1-t) * b1 + t * b2;
Given the normal, n, from your calculation and some slope (from vertical)
threshold angle, a (0-90), after which the colour interpolates between the
snow to the rock depending on the slope, how do I calculate t?
So, let say I have a threshold angle of 60 degrees, how can I test it
against the normal, and get t?
Can you share your code snipit that you used to create the texturemap you
posted?
"Lord Crc" <lordcrc (AT) hotmail (DOT) com> wrote
| Quote: | On Thu, 10 Jun 2004 13:15:46 +1000, "Paul Nicholls" <.> wrote:
Thanks Asbjorn :-)
Btw, adjust the size of Y to determine how "slopy" you want it. Ie, if
it's 1, then since dX or dZ is 1 max too, you wont get any slope
angles < 45 deg. So you prob want to decrease it.
Here's a small sample of a heightmap "texture" which i made by using
the formulate i stated http://lordcrc.no-ip.com/public/hmap.jpg
Just a quicky i made after writing this post :)
- Asbjørn
|
|
|
| Back to top |
|
 |
Paul Nicholls Guest
|
Posted: Thu Jun 10, 2004 6:08 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
erm, I'm actually having trouble using the normal from the calculation you
provided so I can blend the two textures...
lets say I have the two texture rgb values like so:
(r1,g1,b1) = snow (for example)
(r2,g2,b2) = rock (for example)
t = 0..1 (how to calculate)
r := (1-t) * r1 + t * r2;
g := (1-t) * g1 + t * g2;
b := (1-t) * b1 + t * b2;
Given the normal, n, from your calculation and some slope (from vertical)
threshold angle, a (0-90), after which the colour interpolates between the
snow to the rock depending on the slope, how do I calculate t?
So, let say I have a threshold angle of 60 degrees, how can I test it
against the normal, and get t?
Can you share your code snipit that you used to create the texturemap you
posted?
"Lord Crc" <lordcrc (AT) hotmail (DOT) com> wrote
| Quote: | On Thu, 10 Jun 2004 13:15:46 +1000, "Paul Nicholls" <.> wrote:
Thanks Asbjorn :-)
Btw, adjust the size of Y to determine how "slopy" you want it. Ie, if
it's 1, then since dX or dZ is 1 max too, you wont get any slope
angles < 45 deg. So you prob want to decrease it.
Here's a small sample of a heightmap "texture" which i made by using
the formulate i stated http://lordcrc.no-ip.com/public/hmap.jpg
Just a quicky i made after writing this post :)
- Asbjørn
|
|
|
| Back to top |
|
 |
Nils Haeck Guest
|
Posted: Thu Jun 10, 2004 8:18 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Hello Paul,
I normally visualise Z as the height, based on a field in x and y. If you
use that, then:
DeltaZx := h(x+1, y) - h(x-1, y); // The difference in Z due to change in x
over 2 cells
DeltaZy := h(x, y+1) - h(x, y-1); // The difference in Z due to change in y
over 2 cells
Next you calculate the resulting normal vector using crossproduct:
Normal = (2 0 DeltaZx)' x (0 2 DeltaZy) = (-2 * DeltaZx, -2 * DeltaZy, 4),
or (-DeltaZx, -DeltaZy, 2)
As a result, the slope at (x, y) will be:
Slope := sqrt(sqr(DeltaZx) + sqr(DeltaZy)) / 2;
So the slope is the biggest amount of change for each one unit of change in
the XY plane. It assumes you determine this for * based on the 4
neighbouring cells ABCD see below, so special treatment is neccesary at the
edges.
B
A*C
D
You could make a small 2D lookup table for most values of DeltaZx and
DeltaZy (e.g. in a range of -10 .. 10) and only calculate the slope for
values outside of that range. This saves you on the expensive sqrt
instruction.
Kind regards,
Nils Haeck
www.simdesign.nl
"Paul Nicholls" <.> wrote
| Quote: | Hi all, I am interested in finding out the approximate slope at any x,z
point in a Byte filled heightmap...
I am at the moment creating each pixel in the heightmap texture array
depending on the height range, but I now want to add in that if the slope
is
too steep for some terrain types then I will use rock for example instead.
So I need to find out the slope at any x,z point...
Does anyone have a small code snipit that can help me?
Thanks in advance,
Paul Nicholls (Delphi 5/6 Professional)
"The plastic veneer of civilization is easily melted in the heat of the
moment" - Paul Nicholls
[email]paul-nicholls (AT) hotmail (DOT) com[/email]
Replace '-' with '_' to reply
|
|
|
| Back to top |
|
 |
somebody Guest
|
Posted: Thu Jun 10, 2004 11:10 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
"Nils Haeck" <n.haeckno (AT) spamchello (DOT) nl> wrote
| Quote: | Hello Paul,
I normally visualise Z as the height, based on a field in x and y. If you
use that, then:
DeltaZx := h(x+1, y) - h(x-1, y); // The difference in Z due to change in
x
over 2 cells
DeltaZy := h(x, y+1) - h(x, y-1); // The difference in Z due to change in
y
over 2 cells
|
Technically you should have h(x,y) somewhere above, ie either
DeltaZx := h(x+1, y) - h(x, y);
or
DeltaZx := h(x, y) - h(x-1, y);
The problem is, with your definintion, the function
h(x,y) = 255*( (x+y) mod 2)
would have 0 slope everywhere, which is probably not what one would expect.
| Quote: | Next you calculate the resulting normal vector using crossproduct:
Normal = (2 0 DeltaZx)' x (0 2 DeltaZy) = (-2 * DeltaZx, -2 * DeltaZy, 4),
or (-DeltaZx, -DeltaZy, 2)
As a result, the slope at (x, y) will be:
Slope := sqrt(sqr(DeltaZx) + sqr(DeltaZy)) / 2;
|
That's not quite correct either, well, there's no single slope in 3D but a
gradient (a vector quantity). So, depending on how "precise" you want to be
you can calculate the 4 (or gradients approaching from those directions
(for a continuous surface there would only be 2 independent components) and
in this case, take the maximum of the absolute values:
MaxSlope := Max (
Abs(h(x, y) - h(x-1, y)),
Abs(h(x, y) - h(x+1, y)),
Abs(h(x, y) - h(x, y-1)),
Abs(h(x, y) - h(x, y+1)),
0.71*Abs(h(x, y) - h(x-1, y-1)),
0.71*Abs(h(x, y) - h(x+1, y-1)),
0.71*Abs(h(x, y) - h(x-1, y+1)),
0.71*Abs(h(x, y) - h(x+1, y+1)),
);
|
|
| Back to top |
|
 |
Paul Nicholls Guest
|
Posted: Thu Jun 10, 2004 11:14 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Thanks Nils, I'll give it a go :-)
Just one other question, if I have a threshold angle (from vertical),
Athreshold, and when the slope is greater than this value (from the
vertical), how can I calculate t (0-1) for interpolating between 2 textures
(t1 at Athreshold to t2 at 90 degrees)?
Can I do this?
For example:
Athreshold = Cos(60*PI/180); // ignoring the fact I could put in as
radians straight off...
Normal := Normalise(calculated value at height map point)...
D := Dot(Normal,Vector3d(0,1,0));
if(D < Athreshold)then
begin
t := D / Athreshold;
if(t < 0)then
t := 0;
Rt1 := t1.r; // texture 1 colour
Gt1 := t1.g;
Bt1 := t1.b;
Rt2 := t2.r; // texture 2 colour
Gt2 := t2.g;
Bt2 := t2.b;
R := t * Rt1 + (1-t) * Rt2;
G := t * Gt1 + (1-t) * Gt2;
B := t * Bt1 + (1-t) * Bt2;
end;
"Nils Haeck"
| Quote: | Hello Paul,
I normally visualise Z as the height, based on a field in x and y. If you
use that, then:
DeltaZx := h(x+1, y) - h(x-1, y); // The difference in Z due to change in
x
over 2 cells
DeltaZy := h(x, y+1) - h(x, y-1); // The difference in Z due to change in
y
over 2 cells
Next you calculate the resulting normal vector using crossproduct:
Normal = (2 0 DeltaZx)' x (0 2 DeltaZy) = (-2 * DeltaZx, -2 * DeltaZy, 4),
or (-DeltaZx, -DeltaZy, 2)
As a result, the slope at (x, y) will be:
Slope := sqrt(sqr(DeltaZx) + sqr(DeltaZy)) / 2;
So the slope is the biggest amount of change for each one unit of change
in
the XY plane. It assumes you determine this for * based on the 4
neighbouring cells ABCD see below, so special treatment is neccesary at
the
edges.
B
A*C
D
You could make a small 2D lookup table for most values of DeltaZx and
DeltaZy (e.g. in a range of -10 .. 10) and only calculate the slope for
values outside of that range. This saves you on the expensive sqrt
instruction.
Kind regards,
Nils Haeck
www.simdesign.nl
"Paul Nicholls" <.> wrote
Hi all, I am interested in finding out the approximate slope at any x,z
point in a Byte filled heightmap...
I am at the moment creating each pixel in the heightmap texture array
depending on the height range, but I now want to add in that if the
slope
is
too steep for some terrain types then I will use rock for example
instead.
So I need to find out the slope at any x,z point...
Does anyone have a small code snipit that can help me?
Thanks in advance,
Paul Nicholls (Delphi 5/6 Professional)
"The plastic veneer of civilization is easily melted in the heat of the
moment" - Paul Nicholls
[email]paul-nicholls (AT) hotmail (DOT) com[/email]
Replace '-' with '_' to reply
|
|
|
| Back to top |
|
 |
Lord Crc Guest
|
Posted: Thu Jun 10, 2004 11:25 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
On Thu, 10 Jun 2004 16:08:40 +1000, "Paul Nicholls" <.> wrote:
| Quote: | So, let say I have a threshold angle of 60 degrees, how can I test it
against the normal, and get t?
|
I used a power curve to blend in the rocks, however i used a elevation
threshold for WHEN i started to blend in rocks. You can look at that
code to see if does what you want.
| Quote: | Can you share your code snipit that you used to create the texturemap you
posted?
|
http://lordcrc.no-ip.com/public/heightmap_slope.zip
Its on my home box, so it might die, but i'll make it come back up
when i notice :)
- Asbjørn
|
|
| Back to top |
|
 |
Paul Nicholls Guest
|
Posted: Fri Jun 11, 2004 12:04 am Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Thanks, I got the code...I'll take a gander :-)
Cheers,
Paul.
"Lord Crc" <lordcrc (AT) hotmail (DOT) com> wrote
| Quote: | On Thu, 10 Jun 2004 16:08:40 +1000, "Paul Nicholls" <.> wrote:
So, let say I have a threshold angle of 60 degrees, how can I test it
against the normal, and get t?
I used a power curve to blend in the rocks, however i used a elevation
threshold for WHEN i started to blend in rocks. You can look at that
code to see if does what you want.
Can you share your code snipit that you used to create the texturemap you
posted?
http://lordcrc.no-ip.com/public/heightmap_slope.zip
Its on my home box, so it might die, but i'll make it come back up
when i notice :)
- Asbjørn
|
|
|
| Back to top |
|
 |
Nils Haeck Guest
|
Posted: Fri Jun 11, 2004 2:30 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
| Quote: | h(x,y) = 255*( (x+y) mod 2)
would have 0 slope everywhere, which is probably not what one would
expect. |
Sure that's what I would expect. After all, you want the slope for the pixel
value itself. If it goes up by 255 at one end and goes down by 255 at the
other end, the average of that is 0.
You will only get slopes here if you create an image that is twice as big,
or shifted by half a pixel. Calculating slopes on such a high-frequency
image makes no sense anyway due to aliasing effects. You would have to
filter it first and find that in fact the value of all pixels goes to 127.5.
| Quote: | Slope := sqrt(sqr(DeltaZx) + sqr(DeltaZy)) / 2;
That's not quite correct either, well, there's no single slope in 3D but a
|
I don't agree at all. It is absolutely correct when looking at the problem
in 3D. If you have both slopes in X and Y at 1 pixel height change at one
pixel horizontal change, your slope calculation would still yield 1.0 as
slope, while in fact if you come from a 45deg angle you would see a slope of
sqrt(2)=1.41. And a marble rolling down at that point would not roll along
any of the slopes in X and Y but along the 45degree where the slope is
maximum.
Of course it depends on how far you would want to look around, but above
method is generally used for square grids.
Nils
|
|
| Back to top |
|
 |
Nils Haeck Guest
|
Posted: Fri Jun 11, 2004 2:36 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Why not simply convert the slope to degrees?
That way you'll get a value from 0 to 90 degrees (0 being horizontal, 90
being vertical). The 90 will never be reached in a height map of bytes, I
think the theoretical maximum of the slope would be (at the edge)
sqrt(sqr(255) * 2) / 2 = (calculate this yourself)
So the slope angle would be: Angle = arctan(Slope) - in radians
Then you can interpolate like this:
t = Arctan(Slope) / (0.5 * pi);
R := t * Rt1 + (1-t) * Rt2;
G := t * Gt1 + (1-t) * Gt2;
B := t * Bt1 + (1-t) * Bt2;
Or substitute for 0.5 * pi the value of sqrt(sqr(255) * 2) / 2.
Kind regards,
Nils
"Paul Nicholls" <.> wrote
| Quote: | Thanks Nils, I'll give it a go :-)
Just one other question, if I have a threshold angle (from vertical),
Athreshold, and when the slope is greater than this value (from the
vertical), how can I calculate t (0-1) for interpolating between 2
textures
(t1 at Athreshold to t2 at 90 degrees)?
Can I do this?
For example:
Athreshold = Cos(60*PI/180); // ignoring the fact I could put in as
radians straight off...
Normal := Normalise(calculated value at height map point)...
D := Dot(Normal,Vector3d(0,1,0));
if(D < Athreshold)then
begin
t := D / Athreshold;
if(t < 0)then
t := 0;
Rt1 := t1.r; // texture 1 colour
Gt1 := t1.g;
Bt1 := t1.b;
Rt2 := t2.r; // texture 2 colour
Gt2 := t2.g;
Bt2 := t2.b;
R := t * Rt1 + (1-t) * Rt2;
G := t * Gt1 + (1-t) * Gt2;
B := t * Bt1 + (1-t) * Bt2;
end;
"Nils Haeck"
news:40c8bf9b (AT) newsgroups (DOT) borland.com...
Hello Paul,
I normally visualise Z as the height, based on a field in x and y. If
you
use that, then:
DeltaZx := h(x+1, y) - h(x-1, y); // The difference in Z due to change
in
x
over 2 cells
DeltaZy := h(x, y+1) - h(x, y-1); // The difference in Z due to change
in
y
over 2 cells
Next you calculate the resulting normal vector using crossproduct:
Normal = (2 0 DeltaZx)' x (0 2 DeltaZy) = (-2 * DeltaZx, -2 * DeltaZy,
4),
or (-DeltaZx, -DeltaZy, 2)
As a result, the slope at (x, y) will be:
Slope := sqrt(sqr(DeltaZx) + sqr(DeltaZy)) / 2;
So the slope is the biggest amount of change for each one unit of change
in
the XY plane. It assumes you determine this for * based on the 4
neighbouring cells ABCD see below, so special treatment is neccesary at
the
edges.
B
A*C
D
You could make a small 2D lookup table for most values of DeltaZx and
DeltaZy (e.g. in a range of -10 .. 10) and only calculate the slope for
values outside of that range. This saves you on the expensive sqrt
instruction.
Kind regards,
Nils Haeck
www.simdesign.nl
"Paul Nicholls" <.> wrote in message
news:40c7c906 (AT) newsgroups (DOT) borland.com...
Hi all, I am interested in finding out the approximate slope at any
x,z
point in a Byte filled heightmap...
I am at the moment creating each pixel in the heightmap texture array
depending on the height range, but I now want to add in that if the
slope
is
too steep for some terrain types then I will use rock for example
instead.
So I need to find out the slope at any x,z point...
Does anyone have a small code snipit that can help me?
Thanks in advance,
Paul Nicholls (Delphi 5/6 Professional)
"The plastic veneer of civilization is easily melted in the heat of
the
moment" - Paul Nicholls
[email]paul-nicholls (AT) hotmail (DOT) com[/email]
Replace '-' with '_' to reply
|
|
|
| Back to top |
|
 |
Nils Haeck Guest
|
Posted: Fri Jun 11, 2004 2:40 pm Post subject: Re: Finding the 'slope' at a x,z point on a heightmap... |
|
|
Correction:
| Quote: | Or substitute for 0.5 * pi the value of sqrt(sqr(255) * 2) / 2.
|
Or substitute for 0.5 * pi the value of arctan(sqrt(sqr(255) * 2) / 2).
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|