Texture part tiling

Blitz3D Forums/Blitz3D Programming/Texture part tiling

Hy,
I got the following problem:
I created a quad not a Sprite but it looks not different. Now i assigned a part of a texture to this quad. And now i want to scale the quad but i want the texture to keep it´s size (no texture scaling) and it should repeat itself.
I even got a pic:
http://www.blitzforum.de/upload/file.php?id=249
Sorry because it´s in german. But i think the pic says everything.
I hope you understand my question.
And thanks.

I understand your question. I'll get back to you shortly, once i work it out ;o)

I assume your scaling the quad from the centre outwards, and NOT from a corner?

Thanks for your effort.
I´m Scaling the quad with the ScaleEntity mesh,xscale,yscale,1.
I think it´s scaled from the center because it´s midhandled.

Oh, right, so your using scale mesh. Ah, ok. Well, it all depends where the quad was built. If it was built around the 0,0,0 axis by your code, then it will scale from the middle. I'm writing a function to scale the quad and keep the texture correct. But it scales from the quads centre, regardless of where it's built. I'm almost done :o)

I don't think this is possible using a single texture which has 3 other shapes on it. Are you clamping uv .. e.g. flag 16+48? Even if you unclamp the whole texture will repeat .. not just the circle in the top corner.

The only way I can think of is recreating a segmented quad depending on how much you scale it, or premake several versions and swap between them depending on the scale.

Maybe Ross C will prove me wrong ;)

Stevie

@Ross C:
Now i know what you mean. I built my quad around the 0,0,0 point, means 1.vertex:-1,1 2.vertex:1,1 3.vertex:-1,-1 4.vertex:1,-1. And of course thanks.
@Stevie G:
Exactly this is my problem. The only solution i know is to create a whole bunch of quads or to make a new texture.
The first thing isn´t good because i would need much of them and the performance schould be as high as possible.
The second solution is not good, too because i want the texture, wich is not square, seamless.

[edit]I think you mean flags 16+32!
And yes i´m using the flags because i want a pixelperfect texture (with scaling and so on) and without this two flags it would have grey edges.

I don't think this is possible outside of -maybe- writing a custom pixel shader or something. You can't tile just part of an image.

Is this what you mean? I'm not entirely sure. I've still to implement the texture remaining still though.

Graphics3D 800,600
SetBuffer BackBuffer()

Dim vertex_scale#(3,2) ; 4 vertices (0,1,2,3) and 3 axis (0 = x, 1 = y, 2 = z)

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

Global light = CreateLight()

Global mesh = CreateMesh()
Global surf = CreateSurface(mesh)

v0 = AddVertex ( surf,-1,-1,0,0,0)
v1 = AddVertex ( surf, 1,-1,0,1,0)
v2 = AddVertex ( surf,-1, 1,0,0,1)
v3 = AddVertex ( surf, 1, 1,0,1,1)

AddTriangle surf,v0,v2,v1
AddTriangle surf,v1,v2,v3


Global texture = CreateTexture(64,64)
SetBuffer TextureBuffer(texture)
Color 255,255,255
Oval 0,0,63,63
Rect 0,0,63,63,0

SetBuffer BackBuffer()

EntityTexture mesh,texture


Global scale# = 1

While Not KeyHit(1)

	If KeyDown(200) Then
		scale = 1.01
		scale_quad(scale)
	ElseIf KeyDown(208) Then
		scale = 0.99
		scale_quad(scale)
	End If


	UpdateWorld
	RenderWorld
	Flip
Wend
End


Function scale_quad(scale#,index=0)

	vertex_scale(0,0) = VertexX(surf,index)
	vertex_scale(0,1) = VertexY(surf,index)
	vertex_scale(0,2) = VertexZ(surf,index)
	
	vertex_scale(1,0) = VertexX(surf,index+1)
	vertex_scale(1,1) = VertexY(surf,index+1)
	vertex_scale(1,2) = VertexZ(surf,index+1)

	vertex_scale(2,0) = VertexX(surf,index+2)
	vertex_scale(2,1) = VertexY(surf,index+2)
	vertex_scale(2,2) = VertexZ(surf,index+2)

	vertex_scale(3,0) = VertexX(surf,index+3)
	vertex_scale(3,1) = VertexY(surf,index+3)
	vertex_scale(3,2) = VertexZ(surf,index+3)


	centre_x# = (vertex_scale(0,0) + vertex_scale(1,0) + vertex_scale(2,0) + vertex_scale(3,0))/4
	centre_y# = (vertex_scale(0,1) + vertex_scale(1,1) + vertex_scale(2,1) + vertex_scale(3,1))/4
	centre_z# = (vertex_scale(0,2) + vertex_scale(1,2) + vertex_scale(2,2) + vertex_scale(3,2))/4



	For loop = 0 To 3 ; loop through the 4 points
	
		;get the distance from the vertex to it's centre point
		temp_x_dist# = vertex_scale(index+loop,0) - centre_x
		temp_y_dist# = vertex_scale(index+loop,1) - centre_y
		temp_z_dist# = vertex_scale(index+loop,2) - centre_z

		;Scale the vertex
		temp_x_dist = temp_x_dist * scale
		temp_y_dist = temp_y_dist * scale
		temp_z_dist = temp_z_dist * scale

		tx# = centre_x + temp_x_dist
		ty# = centre_y + temp_y_dist
		tz# = centre_z + temp_z_dist

		VertexCoords surf,index+loop,tx,ty,tz
		
		;fix UV's
		u_temp# = VertexU(surf,index+loop) * scale
		v_temp# = VertexV(surf,index+loop) * scale		
;		Stop
		VertexTexCoords surf,index+loop,u_temp,v_temp

	Next
	
End Function


Oh, sorry. I didn't look at your picture :o) Well, you could do as suggested. Simply created a segmented quad, so you can fake wrap the texture around. Limme try that...

Why not copy the part of the texture you want to another texture? Then use this. It would work fine, unless you are doing this specifically for lots of quads, each using this techniqiue.

You can do it like this:
Graphics3D 640,480,0,2
SetBuffer BackBuffer()

dummytex = CreateDummyTex()

camera = CreateCamera()

quad = CreateMesh()
UpdateQuad(quad,1,1,0,0)
EntityTexture quad,dummytex
PositionEntity quad,0,0,10
EntityFX quad,1

s# = 0.0

tu = 0
tv = 0

While Not KeyHit(1)

	If KeyHit(57)
		tu = tu+1
		If tu>1
			tv = tv+1
			tu = 0
			If tv>1 Then tv = 0
		EndIf
	EndIf

	s = s + 1
	UpdateQuad(quad,2.0+Sin(s)*1.5,2.0+Cos(s)*1.5,tu,tv)
	RenderWorld
	
	Color 255,255,255
	Text 0,0,"Space to change texture tile"
	
	Text 0,300,"The texture looks like this:"
	CopyRect 0,0,128,128,0,320,TextureBuffer(dummytex),BackBuffer()
	
	Flip

Wend

End

Function UpdateQuad(mesh,w#,h#,tilex,tiley)

	s = CountSurfaces(mesh)
	If s<1
		surf = CreateSurface(mesh)
	Else
		surf = GetSurface(mesh,1)
	EndIf
	ClearSurface surf

	tx = Floor(w)
	ty = Floor(h)
	tu# = tilex*0.5
	tv# = tiley*0.5

	For x = 0 To tx
		For y = 0 To ty
			x2# = x + 1.0
			y2# = y + 1.0
			tu2# = tu + 0.5
			tv2# = tv + 0.5
			
			If x = tx
				x2 = w
				tu2 = tu + (0.5 * (w-tx))
			EndIf
			
			If y = ty
				y2 = h
				tv2 = tv + (0.5 * (h-ty))
			EndIf
			
			v0 = AddVertex(surf,x ,y ,0,tu ,tv )
			v1 = AddVertex(surf,x2,y ,0,tu2,tv )
			v2 = AddVertex(surf,x2,y2,0,tu2,tv2)
			v3 = AddVertex(surf,x ,y2,0,tu ,tv2)
			AddTriangle surf,v0,v1,v2
			AddTriangle surf,v0,v2,v3
		Next
	Next

	UpdateNormals mesh
	FlipMesh mesh

End Function

Function CreateDummyTex()

	Color 255,0,0
	Oval 4,4,56,56
	
	Color 255,255,0
	Rect 68,4,56,56
	
	Color 0,255,0
	Line  4,68,60,124
	Line 60,68, 4,124
	
	Color 0,255,255
	Rect 68,68,56,56,False
	
	tex = CreateTexture(128,128)
	CopyRect 0,0,128,128,0,0,BackBuffer(),TextureBuffer(tex)

	Return tex

End Function

Made very quickly but it shows how to do it...

"And then you go, and spoil it all, by posting something much better, than miiiiiiiine"

Good stuff fredborg :o)

Sorry, didn't mean to steal your thunder :)

Ok thanks to you all. I didnt check your codes. But whats if i want the texture seamless. The problem is that the texture is non square sized.

Joking man ;o) Your code is far more helpful :o)

Joking man
Ditto :)
But whats if i want the texture seamless. The problem is that the texture is non square sized.
It shouldn't be a problem, if you pad each tile with a single pixel border and offset the uv's slightly you can get it tiling without problems. Square or not makes no difference.

WOW. IT WORKS. Thanks to you all.
The code needs to get a little customized to solve my problem exactly but thats a good starting. THANKS.