Painting a triangle - VertexTexCoords

Blitz3D Forums/Blitz3D Programming/Painting a triangle - VertexTexCoords

siread(Posted 2010) [#1]
I am creating meshes by plotting 4 points, creating the vertices and adding triangles, so basically I end up with a 4 sided poly. (I'm trying to paint different textures on the ground which is completely flat.)

I want to paint this mesh with a brush without the texture getting distorted but I don't know how to calculate the vertex u and v scales.

For example, in this image I want the texture on the right mesh to look identical to the one on the left and not get stretched.



AddVertex(s,x[pointorder[0]],0,-y[pointorder[0]],0,0)
AddVertex(s,x[pointorder[1]],0,-y[pointorder[1]],0,1)
AddVertex(s,x[pointorder[2]],0,-y[pointorder[2]],1,1)
AddVertex(s,x[pointorder[3]],0,-y[pointorder[3]],1,0)
AddTriangle(s,0,1,2)
AddTriangle(s,2,3,0)


Can anyone help?


Ross C(Posted 2010) [#2]
The best way, i can think of, is to find the rightmost vertex, leftmost vertex, the top most vertex, and the bottom most vertex. From those numbers, you can use the vertexX() Y() and Z() (shouldn't need one of those, depending on which plane your flat against) and calculate your UV's

For instance:

Left most vertex = -1,-1,0
Right most vertex = 1,0,0
topmost = -0.5,1,0
bottommost = -1,-1,0

I've generated these vertex-cords, to roughly match your shape. Now, you must scale the width and height of your shape, to fit into 1 unit. I'd choose a scale based on either the height, or the width, so:

rightmost - left most =
1 - -1 = 2

So, for every 2 units, you will span a UV co-ords unit of 1, starting at the leftmost vertex for the x axis, and the bottom-most vertex for the y axis. SO your start co-ords will be the leftmost vertex. so, for every co-ords you will be doing:

leftmost vertex X + difference between leftmost vertex X and the current one.
codewise that would:
VertexX(leftmost) + (VertexX(Vertex you want to get UV's) - VertexX(leftmost))

I'll knock up a demo to demonstrate :)


Ross C(Posted 2010) [#3]
Ok, i got this. Based on the technique i mentioned above. Only problem is, the UV's will scale to the size of the mesh. I suppose you can scale the texture. But it gives you a start point. I've wrapped it into a function, so generate your mesh, include my globals statement containing the "upmost", "leftmost", "rightmost", and "downmost" vars, and of course my leftmost functions etc :)

Press the 2 key to generate the UV's.

Graphics3D 800,600
SetBuffer BackBuffer()


Global camera = CreateCamera()
PositionEntity camera,0,0,-10

Global mesh = CreateMesh()

Global surface = CreateSurface(mesh)

Global leftmost#,rightmost#,upmost#,downmost#

v0 = AddVertex(surface,-1,-1,0)
v1 = AddVertex(surface, 0, 1,0)
v2 = AddVertex(surface, 1, 2,0)
v3 = AddVertex(surface, 3,-3,0)

AddTriangle(surface,v0,v1,v2)
AddTriangle(surface,v0,v2,v3)

UpdateNormals mesh

Global texture = CreateTexture(256,256,1)
SetBuffer TextureBuffer(texture)

	Color 255,255,255
	Rect 0,0,256,256
	Color 255,0,0
	Rect 2,2,252,252
	Color 200,0,0
	Rect 10,10,236,236
	Color 150,0,0
	Rect 30,30,196,196
	
SetBuffer BackBuffer()

Color 255,255,255

EntityTexture mesh,texture

Global light = CreateLight()

While Not KeyHit(1)

	If KeyHit(2) Then
		generate_UVs(surface)
	End If


	RenderWorld
	Flip
	
Wend

Function generate_UVs(surface)

	find_leftmost(surface)
	find_rightmost(surface)
	find_upmost(surface)
	find_downmost(surface)
	
	x_dif# = rightmost - leftmost
	y_dif# = upmost - downmost
	
	Local verts = CountVertices(surface)
	
	For loop = 0 To verts-1
	
		VertexTexCoords(surface, loop, (VertexX(surface,loop)-leftmost)/x_dif, (VertexY(surface,loop)-downmost)/y_dif)
	
	Next
	
End Function

Function find_leftmost(surface)

	leftmost = 99999
	
	Local verts = CountVertices(surface)
	
	For loop = 0 To verts-1
	
		If VertexX(surface,loop) < leftmost Then
			leftmost = VertexX(surface,loop)
		End If
		
	Next
	
End Function

Function find_rightmost(surface)

	rightmost = -99999
	
	Local verts = CountVertices(surface)
	
	For loop = 0 To verts-1
	
		If VertexX(surface,loop) > rightmost Then
			rightmost = VertexX(surface,loop)
		End If
		
	Next
	
End Function

Function find_upmost(surface)

	upmost = -99999
	
	Local verts = CountVertices(surface)
	
	For loop = 0 To verts-1
	
		If VertexY(surface,loop) > upmost Then
			upmost = VertexY(surface,loop)
		End If
		
	Next
	
End Function

Function find_downmost(surface)

	downmost = 99999
	
	Local verts = CountVertices(surface)
	
	For loop = 0 To verts-1
	
		If VertexY(surface,loop) < downmost Then
			downmost = VertexY(surface,loop)
		End If
		
	Next
	
End Function



siread(Posted 2010) [#4]
Awesome! I just needed to scale the texture as you said and it works perfectly. Thanks Ross. :)


Ross C(Posted 2010) [#5]
No worries :)