Ooops
January 26, 2021, 06:34:21 AM

Author Topic: [bb] TextureQuad by BlitzSupport [ 1+ years ago ]  (Read 471 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bb] TextureQuad by BlitzSupport [ 1+ years ago ]
« on: June 29, 2017, 12:28:38 AM »
Title : TextureQuad
Author : BlitzSupport
Posted : 1+ years ago

Description : This is an attempt -- still in progress -- to render any image onto an arbitrary quad, in something at least approaching a reasonable speed (not 'in-game' speed, though). Any improvements welcome, particularly in fixing the holes!

EDIT: Whoa! 3 times faster in BlitzPlus!!! :)

EDIT 2: Some pictures crash in BlitzPlus but not '3D... investigation needed! Just try another picture if it crashes :)


Code :
Code: BlitzBasic
  1. ; -----------------------------------------------------------------------------
  2. ; 2D quad texturer by james @ hi - toro . com
  3. ; -----------------------------------------------------------------------------
  4.  
  5.  
  6.  
  7.  
  8.  
  9. ; -----------------------------------------------------------------------------
  10. ;                                       **** CHANGE THIS BEFORE RUNNING!!! ****
  11. ; -----------------------------------------------------------------------------
  12.         picture$ = "boing.bmp"                                  ; An image on your hard drive...
  13. ; -----------------------------------------------------------------------------
  14. ; Note: picture size is irrelevant in speed terms; only quad size matters.
  15. ; -----------------------------------------------------------------------------
  16. ; Note also that you can see a very simple demo by uncommenting the appropriate
  17. ; line at the top of the demo section (the simple demo source is at the bottom).
  18. ; -----------------------------------------------------------------------------
  19.  
  20.  
  21.  
  22.  
  23.  
  24. ; -----------------------------------------------------------------------------
  25. ; Current 'issues'...
  26. ; -----------------------------------------------------------------------------
  27. ; Holes in rendered image due to line algorithm. Got some ideas, though feel
  28. ; free to beat me to it. Looking for any speedups too!
  29. ; -----------------------------------------------------------------------------
  30. ; Slight problem with right/bottom edges with certain image sizes. Should be
  31. ; able to sort this!
  32. ; -----------------------------------------------------------------------------
  33.  
  34.  
  35.  
  36.  
  37.  
  38. ; -----------------------------------------------------------------------------
  39. ; Globals and constants required...
  40. ; -----------------------------------------------------------------------------
  41.  
  42. Global GfxWidth, GfxHeight
  43. Const RenderDEBUG = True
  44.  
  45. ; -----------------------------------------------------------------------------
  46. ; Types required...
  47. ; -----------------------------------------------------------------------------
  48.  
  49. Type Quad
  50.         Field x [3]
  51.         Field y [3]
  52. End Type
  53.  
  54. ; -----------------------------------------------------------------------------
  55. ; Functions required...
  56. ; -----------------------------------------------------------------------------
  57.  
  58. Function InitRenderer ()
  59.         GfxWidth = GraphicsWidth () - 1
  60.         GfxHeight = GraphicsHeight () - 1
  61. End Function
  62.  
  63. ; BELOW: x0, y0, etc, are the x/y positions of each corner of the quad. Define
  64. ; them in clockwise order...
  65.  
  66. Function CreateQuad.Quad (x0, y0, x1, y1, x2, y2, x3, y3)
  67.         q.Quad = New Quad
  68.         qx[0] = x0: qy[0] = y0
  69.         qx[1] = x1: qy[1] = y1
  70.         qx[2] = x2: qy[2] = y2
  71.         qx[3] = x3: qy[3] = y3
  72.         Return q
  73. End Function
  74.  
  75. Function Dist# (x0#, y0#, x1#, y1#)
  76.         Return Sqr (((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0)))
  77. End Function
  78.  
  79. Function TextureQuad (q.Quad, image)
  80.  
  81.         ; ----------------------------------------------------------------------------
  82.         ; Check globals have been set...
  83.         ; ----------------------------------------------------------------------------
  84.  
  85.         ; NOTE: RenderDEBUG is a constant set at top of code. Setting it to False will
  86.         ; result in this part of the code not being compiled, so you can leave it in... :)
  87.        
  88.         If RenderDEBUG
  89.                 If (Not GfxWidth) Or (Not GfxHeight)
  90.                         RuntimeError "Programmer error!" + Chr (10) + Chr (10) + "You need to call InitRenderer () after setting graphics mode!"
  91.                 EndIf
  92.         EndIf
  93.        
  94.         ; ----------------------------------------------------------------------------
  95.         ; A quad, with a long side and a short side, points marked...
  96.         ; ----------------------------------------------------------------------------
  97.  
  98.         ;       o---------------
  99.         ;       |0                              ------------                   
  100.         ;       |                                                       ------------o
  101.         ;       |                                                                               |1
  102.         ;       |                                                                               |
  103.         ;       |                                                                               |
  104.         ;       |                                                                               |
  105.         ;       |                                                                               |
  106.         ;       |                                                                               |
  107.         ;       |                                                                               |
  108.         ;       |                                                                               |
  109.         ;       |                                                                               |
  110.         ;       |                                                                               |
  111.         ;       |                                                                               |
  112.         ;       |                                                                               |
  113.         ;       |                                                                               |
  114.         ;       |                                                       ------------o
  115.         ;       |                                       --------                         2
  116.         ;       |                       --------
  117.         ;       o-----------
  118.         ;        3
  119.        
  120.         ; ----------------------------------------------------------------------------
  121.  
  122.  
  123.  
  124.         ; ----------------------------------------------------------------------------
  125.         ; Cache image information...
  126.         ; ----------------------------------------------------------------------------
  127.  
  128.         IW = ImageWidth (image) - 1
  129.         IH = ImageHeight (image) - 1
  130.         IB = ImageBuffer (image)
  131.        
  132.         ; ----------------------------------------------------------------------------
  133.         ; Compare lengths of left side and right side...
  134.         ; ----------------------------------------------------------------------------
  135.  
  136.         leftside# = Dist (qx[0], qy[0], qx[3], qy[3])
  137.         rightside# = Dist (qx[1], qy[1], qx[2], qy[2])
  138.  
  139.         ; ----------------------------------------------------------------------------
  140.         ; Get index numbers for points making up each side...
  141.         ; ----------------------------------------------------------------------------
  142.        
  143.         If leftside > rightside
  144.        
  145.                 ; Left side longer...
  146.                
  147.                 long1  = 0
  148.                 long2  = 3
  149.                
  150.                 short1 = 1
  151.                 short2 = 2
  152.                
  153.                 plotdir = 1
  154.                
  155.         Else
  156.                
  157.                 ; Right side longer...
  158.                
  159.                 long1  = 1
  160.                 long2  = 2
  161.                
  162.                 short1 = 0
  163.                 short2 = 3
  164.                
  165.                 plotdir = -1
  166.                
  167.         EndIf
  168.  
  169.         ; ----------------------------------------------------------------------------
  170.         ; The 'plotdir' variable above corrects mirroring that occurs when right side
  171.         ; is longer (don't ask)...
  172.         ; ----------------------------------------------------------------------------
  173.  
  174.  
  175.  
  176.  
  177.  
  178.         ; ----------------------------------------------------------------------------
  179.         ; OK, now we step down both sides of the quad, using the step size according to
  180.         ; the longer of the two sides...
  181.         ; ----------------------------------------------------------------------------
  182.  
  183.  
  184.  
  185.  
  186.        
  187.         ; ----------------------------------------------------------------------------
  188.         ; Taking the long side, the division used to step down it (stepper)
  189.         ; is 1 / length of line. This is used to move down both sides...
  190.         ; ----------------------------------------------------------------------------
  191.        
  192.         ystepper# = 1.0 / Dist (qx[long1], qy[long1], qx[long2], qy[long2])
  193.  
  194.         ; ----------------------------------------------------------------------------
  195.         ; Since the step size is variable, can't use For... Next, so I use
  196.         ; While... Wend to count up to this value...
  197.         ; ----------------------------------------------------------------------------
  198.                
  199.         ylimit# = 1.0 + ystepper
  200.  
  201.         ; ----------------------------------------------------------------------------
  202.         ; Current position down the sides (will be from 0.0 to 1.0 along the line length)...
  203.         ; ----------------------------------------------------------------------------
  204.        
  205.         ypos# = 0
  206.  
  207.         ; ----------------------------------------------------------------------------
  208.         ; Lock back buffer and image buffer ready for Read/WritePixelFast action...
  209.         ; ----------------------------------------------------------------------------
  210.        
  211.         LockBuffer BackBuffer ()
  212.         LockBuffer IB
  213.        
  214.         ; ----------------------------------------------------------------------------
  215.         ; OK, going down both sides...
  216.         ; ----------------------------------------------------------------------------
  217.                
  218.         While ypos < ylimit
  219.                
  220.                 ; ------------------------------------------------------------------------
  221.                 ; Get x and y position of current point on long side...
  222.                 ; ------------------------------------------------------------------------
  223.                
  224.                 xlong# = (qx[long1] * (1 - ypos) + qx[long2] * ypos)
  225.                 ylong# = (qy[long1] * (1 - ypos) + qy[long2] * ypos)
  226.  
  227.                 ; ------------------------------------------------------------------------
  228.                 ; Get x and y position of current point on short side...
  229.                 ; ------------------------------------------------------------------------
  230.  
  231.                 xshort# = (qx[short1] * (1 - ypos) + qx[short2] * ypos)
  232.                 yshort# = (qy[short1] * (1 - ypos) + qy[short2] * ypos)
  233.  
  234.                 ; ------------------------------------------------------------------------
  235.                 ; Now we need to get the step size to traverse horizontally between the side points...
  236.                 ; ------------------------------------------------------------------------
  237.                
  238.                 xstepper# = 1.0 / Dist (xlong, ylong, xshort, yshort)
  239.  
  240.                 ; ------------------------------------------------------------------------
  241.                 ; Since the step size is variable, can't use For... Next, so I use
  242.                 ; While... Wend to count up to this value...
  243.                 ; ------------------------------------------------------------------------
  244.  
  245.                 xlimit# = 1.0 + xstepper
  246.                
  247.                 ; ------------------------------------------------------------------------
  248.                 ; Current position between the sides (will be from 0.0 to 1.0 along the line length)...
  249.                 ; ------------------------------------------------------------------------
  250.  
  251.                 xpos# = 0
  252.  
  253.                 ; ------------------------------------------------------------------------
  254.                 ; OK, go across between the two current side points...
  255.                 ; ------------------------------------------------------------------------
  256.                
  257.                 While xpos < xlimit
  258.  
  259.                         ; --------------------------------------------------------------------
  260.                         ; Get current x and y position  on horizontal line...
  261.                         ; --------------------------------------------------------------------
  262.                        
  263.                         If plotdir = 1
  264.                                 plotx = ((xlong * (1 - xpos)) + (xshort * xpos))
  265.                                 ploty = ((ylong * (1 - xpos)) + (yshort * xpos))
  266.                         Else
  267.                                 plotx = ((xshort * (1 - xpos)) + (xlong * xpos))
  268.                                 ploty = ((yshort * (1 - xpos)) + (ylong * xpos))
  269.                         EndIf
  270.  
  271.                         ; --------------------------------------------------------------------
  272.                         ; Check the point is on the screen (NOTE GLOBALS GW AND GH)...
  273.                         ; --------------------------------------------------------------------
  274.                        
  275.                         If (plotx > 0) And (ploty > 0)
  276.                                 If (plotx < GfxWidth) And (ploty < GfxHeight)
  277.                                
  278.                                         ; ------------------------------------------------------------
  279.                                         ; Plot pixel from the original image by reading from the fractional
  280.                                         ; position across/down the image (xpos and ypos are from 0.0 to 1.0,
  281.                                         ; remember)...
  282.                                         ; ------------------------------------------------------------
  283.                                        
  284.                                         WritePixelFast plotx, ploty, ReadPixelFast (IW * xpos, IH * ypos, IB)
  285.  
  286.                                 EndIf
  287.                         EndIf
  288.  
  289.                         ; --------------------------------------------------------------------
  290.                         ; Move across current line...
  291.                         ; --------------------------------------------------------------------
  292.                                        
  293.                         xpos = xpos + xstepper
  294.        
  295.                 Wend
  296.                
  297.                 ; ------------------------------------------------------------------------
  298.                 ; Move down sides...
  299.                 ; ------------------------------------------------------------------------
  300.                
  301.                 ypos = ypos + ystepper
  302.  
  303.         Wend
  304.        
  305.         ; ----------------------------------------------------------------------------
  306.         ; Unlock buffers...
  307.         ; ----------------------------------------------------------------------------
  308.  
  309.         UnlockBuffer IB
  310.         UnlockBuffer BackBuffer ()
  311.        
  312. End Function
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319. ; Goto SimpleDemo ; Uncomment for bare-minimum demo (see bottom of source code)...
  320.  
  321.  
  322.  
  323.  
  324. ; -----------------------------------------------------------------------------
  325. ; Demo...
  326. ; -----------------------------------------------------------------------------
  327.  
  328. AppTitle "Grab the circles to move the corners..."
  329.  
  330. Graphics 640, 480, 0, 2
  331. SetBuffer BackBuffer ()
  332.  
  333. InitRenderer ()
  334.  
  335. image = LoadImage (picture$)
  336.  
  337. ; Drawing a 256 x 256 image actual size, though this part isn't important!
  338.  
  339. poly.Quad = CreateQuad (100, 100, 356, 100, 356, 356, 100, 356)
  340.  
  341. ClsColor 64, 96, 128
  342.  
  343. mousepointsize = 16
  344.  
  345. Repeat
  346.  
  347.         If MouseDown (1)
  348.                 If movepoint = False
  349.                         For p = 0 To 3
  350.                                 If Dist (MouseX (), MouseY (), polyx[p], polyy[p]) < mousepointsize
  351.                                         movepoint = True
  352.                                         point = p
  353.                                 EndIf
  354.                         Next
  355.                 EndIf
  356.         Else
  357.                 movepoint = False
  358.         EndIf
  359.  
  360.         If movepoint
  361.                 polyx[point] = MouseX ()
  362.                 polyy[point] = MouseY ()
  363.         EndIf
  364.        
  365.         Cls
  366.  
  367.         drawtime = MilliSecs ()
  368.         TextureQuad (poly, image)
  369.         drawtime = MilliSecs () - drawtime
  370.        
  371.         For p = 0 To 3
  372.                 Oval polyx[p] - mousepointsize / 2, polyy[p] - mousepointsize / 2, mousepointsize, mousepointsize, 0
  373.                 Text polyx[p] + mousepointsize, polyy[p] + mousepointsize, "Point " + p
  374.         Next
  375.  
  376.         Text 20, 20, "Render time (millisecs): " + drawtime
  377.        
  378.         Flip
  379.  
  380. Until KeyHit (1)
  381.  
  382. End
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390. .SimpleDemo
  391.  
  392. ; -----------------------------------------------------------------------------
  393. ; Simpler demo (bare minimum usage)...
  394. ; -----------------------------------------------------------------------------
  395.  
  396. Graphics 640, 480, 0, 2
  397. SetBuffer BackBuffer ()
  398.  
  399. InitRenderer ()
  400.  
  401. poly.Quad = CreateQuad (100, 150, 500, 50, 300, 400, 150, 300)
  402.  
  403. image = LoadImage (picture$)
  404.  
  405. Repeat
  406.         Cls
  407.         TextureQuad (poly, image)
  408.         Flip
  409. Until KeyHit (1)
  410.  
  411. End


Comments :


GW(Posted 1+ years ago)

 Great function!Here is the Blitzmax version with a bug fix:
Code: [Select]
Type tQuad
Field X%[4]
Field Y%[4]
End Type


Function CreateQuad:tQuad(x0%, y0%, x1%, y1%, x2%, y2%, x3%, y3%)
Local q:tquad = New tquad
q.x[0] = x0; q.y[0] = y0
q.x[1] = x1; q.y[1] = y1
q.x[2] = x2; q.y[2] = y2
q.x[3] = x3; q.y[3] = y3
Return q
End Function

Function Dist# (x0#, y0#, x1#, y1#)
Return Sqr (((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0)))
End Function

Function DrawTexturedQuad(q:tquad,Source:TPixmap,Dest:TPixmap)

If Not source Then Return
If Not dest Then Return


Local IW% = source.width - 1
Local IH% = source.height  - 1
'Local IB% = ImageBuffer (image)

Local leftside# = Dist (q.x[0], q.y[0], q.x[3], q.y[3])
Local rightside# = Dist (q.x[1], q.y[1], q.x[2], q.y[2])

Local long1%
Local long2%
Local short1%
Local short2%
Local plotdir%

If leftside > rightside

' Left side longer...

long1  = 0
long2  = 3

short1 = 1
short2 = 2

plotdir = 1

Else

' Right side longer...

long1  = 1
long2  = 2

short1 = 0
short2 = 3

plotdir = -1

EndIf

Local ystepper# = 1.0 / Dist (q.x[long1], q.y[long1], q.x[long2], q.y[long2])
Local ylimit# = 1.0 + ystepper

Local ypos# = 0

Local plotx%,Ploty%

While ypos < ylimit
Local xlong# = (q.x[long1] * (1 - ypos) + q.x[long2] * ypos)
Local ylong# = (q.y[long1] * (1 - ypos) + q.y[long2] * ypos)

Local xshort# = (q.x[short1] * (1 - ypos) + q.x[short2] * ypos)
Local yshort# = (q.y[short1] * (1 - ypos) + q.y[short2] * ypos)

Local xstepper# = 1.0 / Dist (xlong, ylong, xshort, yshort)

Local xlimit# = 1.0 + xstepper

Local xpos# = 0

While xpos < xlimit
If plotdir = 1
plotx = ((xlong * (1 - xpos)) + (xshort * xpos))
ploty = ((ylong * (1 - xpos)) + (yshort * xpos))
Else
plotx = ((xshort * (1 - xpos)) + (xlong * xpos))
ploty = ((yshort * (1 - xpos)) + (ylong * xpos))
EndIf

If (plotx > 0) And (ploty > 0)
If (plotx < dest.width) And (ploty < dest.height) And Int(IW * xpos) < IW And Int(IH * ypos) < IH Then
dest.WritePixel(plotx, ploty, source.ReadPixel(Int(IW * xpos), Int(IH * ypos)) )
'WritePixelFast plotx, ploty, ReadPixelFast (IW * xpos, IH * ypos, IB
EndIf
EndIf

xpos = xpos + xstepper

Wend

ypos = ypos + ystepper
Wend

End Function


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal