Code archives/3D Graphics - Maths/Gradient Of a Triangle

This code has been declared by its author to be Public Domain code.

Download source code

Gradient Of a Triangle by Mr Snidesmin2004
I have written this for use with a function that splits a mesh into a number of surfaces, for various levels of gradient. This is useful if you want to add a cliff texture to the steep triangles of a mesh etc.

The 'Instant cliffs' function is here:
http://blitzbasic.com/codearcs/codearcs.php?code=1094

I'm sure you could think of plenty of other uses for finding a triangle's gradient though. . . :O)
Function TriGradient#(surface%, triangle%)
	Local v0%,v1%,v2%
	Local v0x#, v0y#, v0z#
	Local v1x#, v1y#, v1z#
	Local v2x#, v2y#, v2z#
	Local tx#, ty#, tz#
	Local m1#, m2#, c1#, c2#
	Local ax#, ay#, az#
	Local theta#, argument#, modulus#
	Local i%
	
	;Special case 1: Is the whole triangle parallel to xz-plane?
	v0x = VertexX(surface, TriangleVertex(surface, triangle, 0))
	v0y = VertexY(surface, TriangleVertex(surface, triangle, 0))
	v0z = VertexZ(surface, TriangleVertex(surface, triangle, 0))
	v1x = VertexX(surface, TriangleVertex(surface, triangle, 1))
	v1y = VertexY(surface, TriangleVertex(surface, triangle, 1))
	v1z = VertexZ(surface, TriangleVertex(surface, triangle, 1))
	v2x = VertexX(surface, TriangleVertex(surface, triangle, 2))
	v2y = VertexY(surface, TriangleVertex(surface, triangle, 2))
	v2z = VertexZ(surface, TriangleVertex(surface, triangle, 2))
	If v0y = v1y And v1y = v2y Then
		;Yes, so gradient is 0
		Return 0
	End If
	
	;Step 1:
	;Sort out vertices in order of height (y-axis), v0=bottom, v1=middle, v2=top
	For i=0 To 2
        v% = TriangleVertex(surface, triangle, i)
  		If v0=0 Then v0 = v
		If v2=0 Then v2 = v
		
		If VertexY(surface,v) > VertexY(surface,v2) Then v2 = v
		If VertexY(surface,v) < VertexY(surface,v0) Then v0 = v
    Next
	For i=0 To 2
        v% = TriangleVertex(surface, triangle, i)
  		If v0<>v And v2<>v Then v1 = v
    Next
	v0x = VertexX(surface, v0)
	v0y = VertexY(surface, v0)
	v0z = VertexZ(surface, v0)
	v1x = VertexX(surface, v1)
	v1y = VertexY(surface, v1)
	v1z = VertexZ(surface, v1)
	v2x = VertexX(surface, v2)
	v2y = VertexY(surface, v2)
	v2z = VertexZ(surface, v2)
		
	;Step 2: Translate lowest point To 0,0,0
	tx = v0x
	ty = v0y
	tz = v0z
	v0x = v0x - tx
	v0y = v0y - ty
	v0z = v0z - tz
	v1x = v1x - tx
	v1y = v1y - ty
	v1z = v1z - tz
	v2x = v2x - tx
	v2y = v2y - ty
	v2z = v2z - tz
	
	;Special case 2: Is the line (v1,v2) is parallel to xz-plane?
	If v1y = v2y Then
		;Yes, so invert the triangle in the y-axis
		v0y = v1y
		v1y = 0
		v2y = 0
		;Lowest point is now v2, highest is v0, so swap them:
		tx# = v2x
		ty# = v2y
		tz# = v2z
		v2x = v0x
		v2y = v0y
		v2z = v0z
		v0x = tx
		v0y = ty
		v0z = tz
		;Re-do translation:
		v0x = v0x - tx
		v0y = v0y - ty
		v0z = v0z - tz
		v1x = v1x - tx
		v1y = v1y - ty
		v1z = v1z - tz
		v2x = v2x - tx
		v2y = v2y - ty
		v2z = v2z - tz
	End If
	
	
	;Step 3: Find Point a, such that y(a) = 0 and y is on the line (v2, v1)
	;Line Equations:
	;y=m1x+c1
	;y=m2z+c2
	m1 = (v2y-v1y) / (v2x-v1x)
	m2 = (v2y-v1y) / (v2z-v1z)
	c1 = v1y - m1 * v1x
	c2 = v1y - m1 * v1z
	ay = 0
	ax = -c1/m1
	az = -c2/m2
	
	;Special case 3: is v1 at y=0
	If v1y = 0 Then
		;Yes, therefore a = v1
		ax = v1x
		ay = v1y
		az = v1z
	End If
	
	;Step 4. Rotate all points v0,v1,v2, a about y-axis so that point a is at x=0
	theta# = -ATan2(az, ax)	;Angle to rotate
	;NOTE: Actually only v2's z-component will be used, so let's be lazy and only calculate v2z.
	;;Rotate v0
	;argument# = ATan2(v0z, v0x)
	;modulus# = Sqr(v0x^2 + v0z^2)
	;v0x = modulus * Cos(theta+argument)
	;v0z = modulus * Sin(theta+argument)
	;;Rotate v1
	;argument# = ATan2(v1z, v1x)
	;modulus# = Sqr(v1x^2 + v1z^2)
	;v1x = modulus * Cos(theta+argument)
	;v1z = modulus * Sin(theta+argument)
	;;Rotate v2
	argument# = ATan2(v2z, v2x)
	modulus# = Sqr(v2x^2 + v2z^2)
	;v2x = modulus * Cos(theta+argument)
	v2z = modulus * Sin(theta+argument)
	;;Rotate a
	;argument# = ATan2(az, ax)
	;modulus# = Sqr(ax^2 + az^2)
	;ax = modulus * Cos(theta+argument)
	;az = modulus * Sin(theta+argument)
	
	
	;Step 5. Calculate the gradient, and return the value.
	Return Abs(v2y / v2z)
End Function



Function Test#(v0x#, v0y#, v0z#, v1x#, v1y#, v1z#, v2x#, v2y#, v2z#)
	m% = CreateMesh()
	s% = CreateSurface(m)
	AddVertex s, v0x, v0y, v0z
	AddVertex s, v1x, v1y, v1z
	AddVertex s, v2x, v2y, v2z
	AddTriangle s, 0,1,2
	Return TriGradient(s, 0)
End Function

Graphics3D 800, 600, 0, 2
Print Test(0,0,0,   10,1,0,   20,0,0)
WaitKey
End

Comments

None.

Code Archives Forum