Gradient of a triangle

Blitz3D Forums/Blitz3D Programming/Gradient of a triangle

Mr Snidesmin(Posted 2004) [#1]
Hello,

Does anyone have an algorithm that finds the gradient/slope of a 3D triangle, or know how to do this?

I want to use it to create a function that will split a terrain mesh into 2 surfaces, one containing triangles with a slope less than a critical gradient and ones with triangles with steeper slopes.

In other words, it will split a terrain mesh into a surface for a cliff texture, and a surface for a grass texture with great ease.
I'll post the code in the archives when it's written.


AntonyWells(Posted 2004) [#2]
Try this. Not tested but the theory is sound, so just play with it.

function triGrad#(surface,tri,axis)
local vx#,vy#,vz#,sx#,sy#,sz#
local bx#,by#,bz#
    for v=0 to 2
        vert =triangleVertex(surface,tri,v)
        vx#=vertexX(surface,vert)
        vy#=vertexY(surface,vert)
        vz#=vertexZ(surface,vert)
        if vx<sx sx=vx
        if vx>bx bx=vx
        if vy<sy sy=vy
        if vy>by by=vy
        if vz<sz sz=vz
        if vz>bz bz=vz
    next
    select axis
         case 1 ;X
             return bx-sx
         case 2 ;Y
             return by-sy
         case 3 ;Z
             return bz-sz
    end select
end function


The grad will always be positive, as there's no real way(that I know of) to tell if a tri is going up or going down as it's entirely down to perception...But still, the bigger the grad, the more steep it is..so it makes no diff in your case I don't think.

To get the grad of a tri regardless of axis, try this 'wrapper'

  function triangleGradient#( surface,triangle)
       for j=0 to 2
            tl=tl+triGrad(surface,triangle,j)
       next
       return (tl/3.)
  end function



Mr Snidesmin(Posted 2004) [#3]
hmmm. doesn't seem like that really works I'm afraid. I hope it is that simple though :O)

It needs to work out the maximum gradient of the plane that the 3 points in the triangle define. I've a feeling that this will require a bit of matrix algebra.

I've just found this which gives the equation of a plane.
http://astronomy.swin.edu.au/~pbourke/geometry/planeeq/

I'm now just trying find something that can link this equation to the plane's gradient. . .

Perhaps though, I'm just missing something and it is much simpler. . . if someone thinks of a simple way - please put me out of my misery :O)


AntonyWells(Posted 2004) [#4]
Oh well, the above returns the averaged grad of all 3, not max.

Max/biggest grad would be,

function maxGrad(surface,triangle)
    for v=0 to 2
    grad#=triGrad(surface,triangle,v)
    if grad>big_grad# big_grad=grad
    next
    return big_grad
end function


If that doesn't do the trick we're clearly thinking of differant things ;)


Mr Snidesmin(Posted 2004) [#5]
Yep, we are thinking of different things - your function returns the x,y or z dimension (size) of the triangle. i.e. the width, length or height of the space it occupies, not the gradient.

Thanks for the suggestion though. . . unless I can figure out the maths to calculate the gradient, I might have use the height!


AntonyWells(Posted 2004) [#6]
Well this what happens when I try to act smart. I end up looking stupid. ;)

Good luck, but other than this I'm not sure how else to do it.


ZombieWoof(Posted 2004) [#7]
for any 2 points in 3d

x = x2-x1
y = y2-y1
z = z2-z1
d = sqr(x*x+z*z) ; flat distance from pt1 to pt2
slope = abs(y)/d ; 1=45 degree slope

to find the steepest slope on a triangle, do for each pair of points and take the max slope


Mr Snidesmin(Posted 2004) [#8]
Thanks, that's closer to the mark i think - i had already considered this, but it is possible to have a triangle who's plane is vertical (infinite gradient) but the gradient of each edge could be really small.

For example: (0,0,0)-(10,1,0)-(20,0,0)
In this case, the steepest edge has a gradient of 0.1 but clearly the triangle is vertical.

However, I think I've just thought out a method of calculating the actual gradient without any really nasty maths - just using simple geometry.

It's tricky to visualise or describe without diagrams, but here is the outline as best as I can put it in words.

*NOTE: x(v), y(v) and z(v) are the respective x,y and z coordinates of vertex/point v.

Step1:
sort out vertices in order of height (y-axis), v0=bottom, v1=middle, v2=top

Step2:
find point a, such that y(a) = y(v1) and a is on the line (v0,v2)

step3:
find point b, such that y(b) = y(v1) and x(b) = x(v2) and z(b) = z(v2)

step4:
find point c, such that c is on the line (v1, a) and the angle (v1,b,c) = 90 degrees

step5:
dy = y(v2) - y(v1)
dx = x(b) - x(c)
dz = z(b) - z(c)
dxz = sqr(dx*dx + dz*dz)
GRADIENT = dy/dxz

I think I can manage to implement this.
If it works, I'll put it in the archives. . .


ZombieWoof(Posted 2004) [#9]
Sorry -- I made the assumption that your terrain was originally constructed from height map data such that true vertical surfaces wouldnt be possible.

The general solution is:
1. translate lowest point to 0,0,0
2. extend line between other 2 points to touch y=0
3. touch point becomes new middle point of triangle
4. rotate triangle so that bottom 2 points are at x=0, y=0
5. highest point y/z = slope, if z=0, its vertical


Mr Snidesmin(Posted 2004) [#10]
Thanks ZombieWoof, that looks reasonable to code too. Probably even simpler than my method.

I'll give it a try. . .


DarkEagle(Posted 2004) [#11]
cant you get the normals of the 3 vertices of the triangle and take an average, then compare triangles by normals rather than gradient?


ZombieWoof(Posted 2004) [#12]
Thats what I get for not being that deep into 3D mesh stuff

simpler solution, average the normals of the vertices, the normal the opposite of the slope, compute:

x = (nx1+nx2+nx3)/3
y = (ny1+ny2+ny3)/3
z = (nz1+nz2+nz3)/3
d = sqr(x*x+z*z)
s = d/y                  ; was y/d in last version


if y=0, the triangle is flat, no slope
slope = 1 is 45 deg, higher numbers are steeper


Mr Snidesmin(Posted 2004) [#13]
I have just finished coding the solution using ZombieWoof's second method. This is more precise than using the normals, because it's possible for the vertex normals to be wrong, or used differently for various unusual lighting effects etc.

The code is here:
http://blitzbasic.com/codearcs/codearcs.php?code=1093