gah! How to clip rotated rectangles.

BlitzMax Forums/BlitzMax Programming/gah! How to clip rotated rectangles.

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

It's probably not possible, but I'll post anyway incase any of you clever boffins have any ideas.

Basically I'm NOT using the BMax Viewport command because it fails on some videocards (as in, it does nothing) - I've seen it with my own eyes.

I'm using this very useful code by Ian Duff:

' -----------------------------------------------------------------------------
' 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).
  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))
                
    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)
?Win32
  EndIf
?
  
  Function ccDrawImageAreaPow2Size%(n)
    Local ry = 1
    
    While ry < n
      ry :* 2
    Wend
    
    Return ry
  End Function
End Function


This works great and I can pass in parameters to basically draw a clipped rectangle to my view port, like this:

' -----------------------------------------------------------------------------
' ccClipImageToViewport: Clips an image into a "safe" viewport (doesn't use BMax viewport)
' -----------------------------------------------------------------------------
Function ccClipImageToViewport(image:TImage, imagex#, imagey#, ViewportX#, ViewPortY#, ViewPortW#, ViewPortH#, offsetx=0, offsety=0)
	'Perform basic clipping first by checking to see if the image is completely
	'outside of the viewport.
	'Note that images are drawn from the top left, not midhandled or anything else.
	Local w = ImageWidth(image)
	Local h = ImageHeight(image)
	
	If imagex+w>=ViewportX And imagex-w<ViewportX+ViewportW and..
		imagey+h>=ViewportY And imagey-h<ViewportY+ViewportH Then
		'Clip left and top
		Local startx#=ViewportX-imagex
		Local starty#=ViewportY-imagey
		If startx<0 Then startx=0 'clamp normal values
		If starty<0 Then starty=0 'clamp normal values
		'Clip right and bottom
		Local endx#=(imagex+w)-(ViewportX+ViewportW)
		Local endy#=(imagey+h)-(ViewportY+ViewportH)
		If endx<0 Then endx=0 'clamp normal values
		If endy<0 Then endy=0 'clamp normal values
		ccDrawImageArea(Image, imageX+startX+offsetx, imagey+starty+offsety, startx, starty, w-startx-endx, h-starty-endy)
	EndIf
End Function

Probably the above function can be optimised, please let me know if you can think of a smarter way to do it.

Anyway ... If I use SetRotation and call the above code, the image is drawn rotated fine but of course it's clipped BEFORE the rotation and thus weird stuff happens to it like bits appear missing inside the viewport and other bits poke out the viewport :-(

I want to rotate it and then draw it clipped AFTER the rotation so that the clipping rectangle is at Rotation 0, not the same angle as the rotated image. Make sense? If not I'll post an image.

Oh and it has to be fast enough to use at runtime, not precalculated (e.g. using pixmaps etc).

Anyone got any ideas how to resolve this as I'm stuck because my DX/GL knowledge is minimal. Many thanks in advance.