Fill an area with an image

BlitzMax Forums/BlitzMax Programming/Fill an area with an image

GfK(Posted 2008) [#1]
I want to fill an area of any position, width and height, with a repeated, tiled image.

How is this possible?

I've been told to avoid SetViewport because it doesn't work on some cards. Is this true?


Grey Alien(Posted 2008) [#2]
Yes it's true I've seen it with my own eyes.

' -----------------------------------------------------------------------------
' ccDrawImageArea: Draws part of an image.
' (by Ian Duff)
' -----------------------------------------------------------------------------
Function ccDrawImageArea(image:TImage, x#, y#, rx#, ry#, rw#, rh#, theframe=0)
 'Note that this code works fine in DirectX or OpenGL on PCs - it autodetects (Grey Alien).
 'Warning: make sure that none of your images have pixels right on the edge otherwise
 'when drawing clipped, they may leave smear in the clipped area! (Grey Alien).
  Local origin_x#, origin_y# ; GetOrigin (origin_x, origin_y)
  Local tw = ccDrawImageAreaPow2Size(image.width)
  Local th = ccDrawImageAreaPow2Size(image.height)
  Local rw1#  = rx + rw
  Local rh1#  = ry + rh
  Local x0# = -image.handle_x, x1# = x0 + rw
  Local y0# = -image.handle_y, y1# = y0 + rh
  
  If rw1 > image.width
    x1 = x0 + rw + image.width - rw1
    rw1 = image.width
  EndIf
   
  If rh1 > image.height
    y1 = y0 + rh + image.height - rh1
    rh1 = image.height
  EndIf
?Win32
  If TD3D7ImageFrame(image.frame(theframe))
    Local frame:TD3D7ImageFrame = TD3D7ImageFrame(image.frame(theframe))
    
    frame.setUV(rx / tw, ry / th, rw1 / tw, rh1 / th)
	frame.Draw x0, y0, x1, y1, x + origin_x, y + origin_y
    frame.setUV(0, 0, image.width / Float(tw), image.height / Float(th))
  Else
?
    Local frameA:TGLImageFrame = TGLImageFrame (image.frame(theframe))
    'Protect against frameA being null due to alt+tab. (Grey Alien)
	If frameA<>Null Then
	    frameA.u0 = rx / tw
	    frameA.v0 = ry / th
	    frameA.u1 = rw1 / tw
	    frameA.v1 = rh1 / th
	    
	    frameA.Draw x0, y0, x1, y1, x + origin_x, y + origin_y
	    
	    frameA.u0 = 0
	    frameA.v0 = 0
	    frameA.u1 = image.width / Float(tw)
	    frameA.v1 = image.height / Float(th)
	EndIf
?Win32
  EndIf
?
  
  Function ccDrawImageAreaPow2Size%(n)
    Local ry = 1
    
    While ry < n
      ry :* 2
    Wend
    
    Return ry
  End Function
End Function


Calc how many whole tiles you can fit and draw them, then use the above code for the partial rects. The above code doesn't work with rotated textures.


Yan(Posted 2008) [#3]
...Or...

Enable texture repeat and draw a textured poly with its UVs set accordingly.


GfK(Posted 2008) [#4]
Enable texture repeat and draw a textured poly with its UVs set accordingly.
...how do I do that, then?


Grey Alien(Posted 2008) [#5]
You'll need DX and OpenGL API calls for that (probably). I've no idea how, never delved into it that far. The expert techies round here seem to always deliver the goods ;-)


Yan(Posted 2008) [#6]



Grey Alien(Posted 2008) [#7]
Hotness! Looks like this works with rotated textures too yes?

Now GfK, you better say thanks. ;-)


Yan(Posted 2008) [#8]
You can rotate the poly using Max2D's normal transformation commands.

If you wanted to rotate the 'tiles', you'd need to manually rotate the poly's UVs.


Grey Alien(Posted 2008) [#9]
I tried something like that before with the code I posted at the top but it just wasn't working how I expected. I wanted to rotate the original texture, capture a small part of it in a vertical rectangle (so effectively the rotation was clipped to a rectangle) and then draw it on-screen. It was turdish.


Raz(Posted 2012) [#10]
Hey not sure when this was posted, but does Yan's example still work for everyone?

The SetTextureRepeat function kicks up a fuss on this line

glBindTexture GL_TEXTURE_2D, TGLImageFrame(image.Frame(0)).name

Unhandled Exception: Attempt to access field or method of Null object


Floyd(Posted 2012) [#11]
The OpenGL driver used to be the default on Windows. Now you must explicitly enable it. That's the commented out line at the start of the code.


Raz(Posted 2012) [#12]
Got ya, thanks :)