Single Dimension Rotation

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
NorbyDroid
Posts: 70
Joined: May 21, 2016 22:55

Single Dimension Rotation

Post by NorbyDroid »

This may need some work, but here is some code for rotatiting a single dimension array of data that is size width,width. Converting this to a two-dimentional array should be a snap.

Code: Select all

0 Degrees: y*width+x
90 Degrees: ((width*width)-width)+y-(x*width)
180 Degrees: ((width*width)-1)-(y*width)-x
270 Degrees: (width-1)-y+(x*width)
`
Please test it out and let me know if there are any issues.
If anyone can improve it, please do and share it here.

Thanks.
NorbyDroid
Posts: 70
Joined: May 21, 2016 22:55

Re: Single Dimension Rotation

Post by NorbyDroid »

I have successfy tested the routines usin 4x4, 8x8, and 24x24 single dimension string of data. I will be postin a demo later to show it in action.
NorbyDroid
Posts: 70
Joined: May 21, 2016 22:55

Re: Single Dimension Rotation

Post by NorbyDroid »

Here is a quick demo showin 4x4, 8x8, and 24x24 sprites rotated usin the info in my first post. Enjoy.

Code: Select all

Function Rotate (tArt As String, iWidth As Integer, iDegres As Integer) As String
  Dim tRotate As String

  Dim tPos As Integer, tWidth As Integer
  Dim t As Integer, x As Integer, y As Integer
  Dim t1 As Integer, t2 As Integer, t3 As Integer

  tWidth=iWidth*iWidth
  t1=tWidth-iWidth: t2=tWidth-1: t3=iWidth-1

  For y=0 To iWidth-1
    For x=0 To iWidth-1
      Select Case iDegres
      	Case   0: tPos=y*iWidth+x
      	Case  90: tPos=t1+y-(x*iWidth)
      	Case 180: tPos=t2-(y*iWidth)-x
      	Case 270: tPos=t3-y+(x*iWidth)
      End Select

      tRotate=tRotate+Mid$(tArt, tPos+1, 1)
    Next
  Next

  Rotate = tRotate
End Function

Sub ViewArt (xPos As Integer, yPos As Integer, tArt As String, iWidth As Integer)
  Dim x As Integer, y As Integer, tChar As Integer
  
  For y=0 To iWidth-1
    For x=0 To iWidth-1
      If Mid(tArt, (y*iWidth+x)+1, 1)="0" Then tChar=32 Else tChar=219

      Locate y+yPos, x+xPos: Print Chr(tChar)
    Next
  Next
End Sub

Sub Demo(Sprite As String, wSprite As Integer)
Dim t As Integer

Dim Sprite90  As String
Dim Sprite180 As String
Dim Sprite270 As String

Sprite90 =Rotate(Sprite, wSprite, 90)
Sprite180=Rotate(Sprite, wSprite, 180)
Sprite270=Rotate(Sprite, wSprite, 270)

For t=1 To 4
  ViewArt 3, 2, Sprite, wSprite

  Sleep 500
  If Inkey=Chr(27) Then End
  
  ViewArt 3, 2, Sprite90, wSprite

  Sleep 500
  If Inkey=Chr(27) Then End

  ViewArt 3, 2, Sprite180, wSprite

  Sleep 500
  If Inkey=Chr(27) Then End

  ViewArt 3, 2, Sprite270, wSprite

  Sleep 500
  If Inkey=Chr(27) Then End
Next
End Sub

Dim t As Integer
Dim Sprite1 As String, Sprite2 As String, Sprite3 As String, tData As String

ScreenRes 208,208,32

' 4x4 Letter A
For t=1 To 4: Read tData: Sprite1=Sprite1+tData: Next: Demo Sprite1, 4

Data "1111"
Data "1001"
Data "1111"
Data "1001"

' 8x8 Copyright symbol
For t=1 To 8: Read tData: Sprite2=Sprite2+tData: Next: Demo Sprite2, 8

Data "00111100"
Data "01000010"
Data "10011001"
Data "10100001"
Data "10100001"
Data "10011001"
Data "01000010"
Data "00111100"

' TI Logo (24x24 Sprite)
For t=1 To 24: Read tData: Sprite3=Sprite3+tData: Next: Demo Sprite3, 24

Data "000000011111110000000000"
Data "000000110000010010000000"
Data "000000110000010101000000"
Data "000000110000010101000000"
Data "000000110000010010000000"
Data "000000110000011000000000"
Data "000000110000001000001100"
Data "000000110000110000010010"
Data "111111110001100110111010"
Data "100000000010000110001010"
Data "100000000010000110001010"
Data "110000000011110110111010"
Data "011000000000010110100001"
Data "001100000000010110100001"
Data "000110000000010110100001"
Data "000011000000010000100010"
Data "000001111110001001001100"
Data "000000000010000110010000"
Data "000000000011000000100000"
Data "000000000001100001000000"
Data "000000000000110001000000"
Data "000000000000011000100000"
Data "000000000000001111100000"
Data "000000000000000000000000"
 
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Single Dimension Rotation

Post by marcov »

Note that that expressions with the loopvar are often strength reduced.

So you for ((width*width)-width)+y-(x*width)

you calculate ((width*width)-width) and then increase that value by one in the Y loop and decrease with WIDTH in the X loop.

There are also two notes about the algorithm:
- jpg's are already a matrix of 8x8 squares internally that you can directly manipulating instead of first unpacking to a bitmap in memory.
- Note that this is not particularly fast for large arrays since this trashes the cache. For better large array (image) performance search for loop tiling where you rotate small squares at a time (typically 8x8 or 64x64) Some pascal code of mine for that is in this SO thread
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Single Dimension Rotation

Post by badidea »

NorbyDroid wrote:If anyone can improve it, please do and share it here.
Well, here is the proof for rotating a vector around any angle: https://matthew-brett.github.io/teachin ... on_2d.html
But if you have an image, you do not want to rotate around the origin, but around the center.
So first translate by half image width & height, then rotate, then translate back.
If you all write that down, something like yours should come out. Too lazy to do all that.
And I did that for any angle in 2007: Sprite rotation
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Single Dimension Rotation

Post by marcov »

As Angros said way back:
Cos and Sin are slow
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Single Dimension Rotation

Post by D.J.Peters »

For fast rotating images you can try MultiPut also.

Joshy
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Single Dimension Rotation

Post by dodicat »

3D rotate an image.(not on Earth)

Code: Select all

#cmdline "-gen gcc -Wc -O2"
Type V3
    As Single x,y,z
    As Ulong col
End Type
Type _float As v3


sub RotateArray(wa() As V3,result() As V3,angle As _float,centre As V3,flag As Long=0,eyepoint As V3=(400,300,900))
    Dim As Single dx,dy,dz,w
    Dim As Single SinAX=Sin(angle.x)
    Dim As Single SinAY=Sin(angle.y)
    Dim As Single SinAZ=Sin(angle.z)
    Dim As Single CosAX=Cos(angle.x)
    Dim As Single CosAY=Cos(angle.y)
    Dim As Single CosAZ=Cos(angle.z)
    Redim result(Lbound(wa) To Ubound(wa))
    For z As Long=Lbound(wa) To Ubound(wa)
        dx=wa(z).x-centre.x
        dy=wa(z).y-centre.y
        dz=wa(z).z-centre.z
        Result(z).x=((Cosay*Cosaz)*dx+(-Cosax*Sinaz+Sinax*Sinay*Cosaz)*dy+(Sinax*Sinaz+Cosax*Sinay*Cosaz)*dz)+centre.x
        result(z).y=((Cosay*Sinaz)*dx+(Cosax*Cosaz+Sinax*Sinay*Sinaz)*dy+(-Sinax*Cosaz+Cosax*Sinay*Sinaz)*dz)+centre.y
        result(z).z=((-Sinay)*dx+(Sinax*Cosay)*dy+(Cosax*Cosay)*dz)+centre.z
        #macro perspective()
        w = 1 + (result(z).z/eyepoint.z)
        result(z).x = (result(z).x-eyepoint.x)/w+eyepoint.x 
        result(z).y = (result(z).y-eyepoint.y)/w+eyepoint.y 
        result(z).z = (result(z).z-eyepoint.z)/w+eyepoint.z
        #endmacro
        If flag Then: perspective():End If
        result(z).col=wa(z).col
    Next z
End sub

Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,_lastsleeptime,t3,frames
    Var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=_lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    _lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function

Screen 20,32
Dim As Long counter,fps
Redim As v3 a(1 to 300*300*2)
Dim As Any Ptr i=Imagecreate(1024,768,Rgb(0,0,50))
For y As Long=0 To 299
    For x As Long=0 To 299
        counter+=1
        a(counter)=Type(x,y,0,Rgb(x*2, x*2 xor y*2,y*2))
        If counter Mod 200=0 Then  Pset i,(Rnd*1024,Rnd*768),Rgb(x, x xor y,y)
    Next
Next
Redim Preserve a(1 To counter)
Dim As v3 result(1 To counter)

Dim As _float ang
Do
    ang.z+=.03
    ang.y+=.02
    ang.x+=.02
    rotatearray(a(),result(),ang,Type(150,150,0),1)
    Screenlock
    Cls
    Put(0,0),i,Pset
    For n As Long=1 To counter
        Circle(result(n).x+300,result(n).y+250),1,result(n).col,,,,f
    Next n
    Draw String (10,10),"FPS= "&fps
    Screenunlock
    Sleep regulate(35,fps)
Loop Until Inkey=Chr(27)
Imagedestroy i
 
Post Reply