Textured Poly (again)

BlitzMax Forums/BlitzMax Programming/Textured Poly (again)

Hezkore(Posted 2013) [#1]
I know this has been asked many many times and answers has been given, but I want a textured polygon, most importantly a triangle textured.
But here's the tricky part... I need the texture to NOT move around when the triangle's moved about or stretched, and I haven't found any post on the forum or code archive showing this.

CLICK HERE to see a working DrawTexturedPoly function with repeating textures.

Oh and also, this will only be used in OpenGL, so the entire part of the example about D3D is useless.

UPDATE: This example will show the "problem"
Move your mouse around and watch as the texture stretches.
I can't figure out how to set the UV coords to make look good when it's stretched about.
Strict

SetGraphicsDriver GLMax2DDriver()
Graphics 800, 600, 0

Local img:TImage = LoadImage("test.png", FILTEREDIMAGE | MIPMAPPEDIMAGE)
Assert img Else "Oi...Where's yer samples gone?"

SetTextureRepeat(img)

Repeat
	Cls
	
	Local tileScale# = 1
	Local UMax# = 740.0 / (img.pixmaps[0].width * tileScale#)
	Local VMax# = 540.0 / (img.Pixmaps[0].height * tileScale#)
	
	'SetTextureRepeat(img)' Strictly speaking you should set and reset when needed, I spose.
	DrawTexturedPoly([30.0, 30.0, 0.0, 0.0, ..				'TL
										770.0, 30.0, UMax#, 0.0, ..			'TR
										Float(MouseX()), Float(MouseY()), UMax#, VMax# ..	'BR
						  			],  ..		'BL
										img)
	 'SetTextureRepeat(img, false)
	
	Flip
Until KeyHit(KEY_ESCAPE) Or AppTerminate()

End

' Under DX, *ALL* images drawn will have repeating textures. Generally not a problem but be forewarned.
Function SetTextureRepeat(image:TImage, rep=True)
	Assert (image.width = Pow2Size(image.width)) And (image.height = Pow2Size(image.height)),..
					"Image width and height must be a power of two"
	Local D3D7Driver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)
	
	If rep
?Win32 
		If D3D7Driver
			'DX
			D3D7Driver.device.SetTextureStageState 0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP
		Else
?
			'GL		
			glBindTexture GL_TEXTURE_2D, TGLImageFrame(image.Frame(0)).name
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT
?Win32
		EndIf
?
	Else
?Win32
		If D3D7Driver
			'DX
			D3D7Driver.device.SetTextureStageState 0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP
		Else
?
			'GL
			glBindTexture GL_TEXTURE_2D, TGLImageFrame(image.Frame(0)).name
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE
?Win32
		EndIf
?
	EndIf
End Function

Function DrawTexturedPoly(xyuv#[], image:TImage, frame=0, fan=1)
	Local textureWidthRatio! = Double(image.width) / Pow2Size(image.width)
	Local textureHeightRatio! = Double(image.height) / Pow2Size(image.height)
	Local hx#, hy#, ox#, oy#
	
	GetHandle(hx#, hy#)
	GetOrigin(ox#, oy#)
?Win32
	Local DXDriver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)	
	If DXDriver
		'DX
		Local verts#[(xyuv#.length / 4) * 6]
		Local vCount
		
		For Local c=0 Until xyuv#.length Step 4
			verts#[vCount] = ((xyuv#[c] - hx#) * DXDriver.ix#) + ((xyuv#[c + 1] - hy#) * DXDriver.iy#) + ox#
			verts#[vCount + 1] = ((xyuv#[c] - hx#) * DXDriver.jx#) + ((xyuv#[c + 1] - hy#) * DXDriver.jy#) + oy#
			verts#[vCount + 2] = 0
			(Int Ptr(Float Ptr(verts#)))[vCount + 3] = DXDriver.drawcolor
			verts#[vCount + 4] = xyuv#[c + 2] * textureWidthRatio!
			verts#[vCount + 5] = xyuv#[c + 3] * textureHeightRatio!
			
			vCount :+ 6
		Next

			DXDriver.SetActiveFrame(TD3D7ImageFrame(image.Frame(frame)))
			If fan
				DXDriver.device.DrawPrimitive(D3DPT_TRIANGLEFAN, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, verts#, xyuv#.length / 4, 0)
			Else
				DXDriver.device.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, verts#, xyuv#.length / 4, 0)
			EndIf
	Else
?
		'GL
		'Can't get at GLMax2D's transform info, so...
		Local sx#, sy#
		GetScale(sx#, sy#)
		
		glPushMatrix()
	
		glBindTexture(GL_TEXTURE_2D, TGLImageFrame(image.Frame(frame)).name)
		glEnable(GL_TEXTURE_2D)	
		
		glTranslatef(ox#, oy#, 0.0)		
		glRotatef(GetRotation(), 0.0, 0.0, 1.0)
		glScalef(sx#, sy#, 1.0) 
		
		If fan Then glBegin(GL_TRIANGLE_FAN) Else glBegin(GL_TRIANGLE_STRIP)
		
		For Local c=0 Until xyuv#.length Step 4
			glTexCoord2f(xyuv#[c + 2] * textureWidthRatio!, xyuv#[c + 3] * textureHeightRatio!)
			glVertex2f(xyuv#[c] - hx#, xyuv#[c + 1] - hy#)
		Next
		
		glEnd
	
		glDisable(GL_TEXTURE_2D)
		glPopMatrix()
?Win32
	EndIf
?
End Function

Function Pow2Size(n)
	Local t = 1
	
	While t < n
		t :* 2
	Wend
	
	Return t
End Function



matibee(Posted 2013) [#2]
You can work out the uv coords relative to the screen position.




Hezkore(Posted 2013) [#3]
-REMOVED (No idea how this happened?)-


Hezkore(Posted 2013) [#4]
Thank you matibee, you've saved my day!

Here's a "cleaned" version with _only_ OpenGL support and that automatically sets the UV coords for you.



BlitzSupport(Posted 2013) [#5]
Nice -- seems like it would work as a simple masking/light cone effect.


Hezkore(Posted 2013) [#6]
Anyone able to get this working together with gl_polygon_smooth?
Or would gl_polygon_smooth not be related at all here?