search for a rotation algorithm

Windows specific questions.
Post Reply
Mysoft
Posts: 836
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

search for a rotation algorithm

Post by Mysoft »

i´m searching for one algorihtm that do gfx block rotates like
blockrotate (ANGLE,ORGBLOCK,ROTATEDBLOCK)
i have made one a time ago, but i think that the result is not fast :P
anyone know something?
Zamaster
Posts: 1025
Joined: Jun 20, 2005 21:40
Contact:

Post by Zamaster »

Sure, Its called inverse pixel rotation. Here's some QB code, should work in FB with a little modifying of the PCOPY statement.

Code: Select all

'_____________________________________________________________________________
'-----------------------------------------------------------------------------
'EXAM9.BAS - Example of Inverse Pixel Transformations
'By: Chris Brown
'
DECLARE FUNCTION num$ (value%) 'Function that removes extra space character when
'converting numbers to strings
TYPE BallType 'Variables for the baseballs
exist AS INTEGER 'Does it exist
x AS INTEGER 'Where is it, X positions
y AS INTEGER 'Y position
xspeed AS INTEGER 'How fast its moving along the X axis
yspeed AS INTEGER 'How fast its moving along the Y axis
size AS INTEGER 'How big it is
angle AS INTEGER 'What is its angle of rotation
aspd AS INTEGER 'How fast its rotating
scnsd AS INTEGER 'What side of the screen it came from
hts AS INTEGER 'Center of rotation scaled up by half of SIN, COS table size
END TYPE
DECLARE SUB DrawSprite (x%, y%, angl%, sze%, htsd%) 'Draws the sprite
DECLARE SUB PutRGB (col%) 'Places a color in the palette from RCol%, GCol%,
'and BCol% values
SCREEN 7, , 1, 2 'Use screen 7 for easy double buffering

RANDOMIZE TIMER 'New random numbers every time

DIM SHARED Sprite%(23, 23), setblack% 'Sprite data and setblack%, a variable
'that says whether or not to put the color black in the palette
DIM SHARED SINx%(1 TO 360), COSx%(1 TO 360), RCol%, GCol%, BCol% 'SIN and COS
'tables and RCol%, GCol%, BCol% values used for PutRGB

maxballs% = 10 'How many baseballs are floating around

DIM BaseBalls(1 TO maxballs%) AS BallType 'Define baseball data array

setblack% = 0 'We havent put black in the palette yet


'Create SIN, COS table and scale it up by 512
FOR a% = 1 TO 360
SINx%(a%) = SIN(a% * (3.14 / 180)) * 512
COSx%(a%) = COS(a% * (3.14 / 180)) * 512
NEXT a%

'Get colors from the palette data and put them in the palette
RESTORE Pal
READ Plength% 'How many colors are there?
FOR i% = 1 TO Plength% 'Put that many in
READ RCol%, GCol%, BCol%
PutRGB i%
IF i% = 7 THEN OUT &H3C7, 16: OUT &H3C8, 16 'This is required in screen 7 to
'put colors past color 7
NEXT i%

'read the sprite data and store it
RESTORE SpriteDat
FOR y% = 0 TO 23
FOR x% = 0 TO 23
READ col%
Sprite%(x%, y%) = col% + 1 'Plus 1 to keep 0 untouched
NEXT x%
NEXT y%


DO

IF INT(RND * 12) = 10 THEN 'Randomly crate baseball
FOR i% = 1 TO maxballs%
IF BaseBalls(i%).exist = 0 THEN 'If we have an extra space for one
BaseBalls(i%).exist = 1 'Put it there
sos% = INT(RND * 4) + 1 'What side of the screen should it come from
SELECT CASE sos%
CASE 1 'The top of the screen
'Next bunch of variables direct the baseball toward the middle of the screen
BaseBalls(i%).x = INT(RND * 350) - 32
BaseBalls(i%).y = -31
BaseBalls(i%).xspeed = INT(RND * 3) + 1
IF BaseBalls(i%).x > 160 THEN BaseBalls(i%).xspeed = BaseBalls(i%).xspeed * -1
BaseBalls(i%).yspeed = INT(RND * 6) + 3
CASE 2 'The right side of the screen
'Next bunch of variables direct the baseball toward the middle of the screen
BaseBalls(i%).x = 352
BaseBalls(i%).y = INT(RND * 230) - 32
BaseBalls(i%).yspeed = INT(RND * 3) + 1
IF BaseBalls(i%).y > 100 THEN BaseBalls(i%).yspeed = BaseBalls(i%).yspeed * -1
BaseBalls(i%).xspeed = (INT(RND * 6) + 3) * -1
CASE 3 'The bottom of the screen
'Next bunch of variables direct the baseball toward the middle of the screen  
BaseBalls(i%).x = INT(RND * 350) - 32
BaseBalls(i%).y = 232
BaseBalls(i%).xspeed = INT(RND * 3) + 1
IF BaseBalls(i%).x > 160 THEN BaseBalls(i%).xspeed = BaseBalls(i%).xspeed * -1
BaseBalls(i%).yspeed = (INT(RND * 6) + 3) * -1
CASE 4 'The left side of the screen
'Next bunch of variables direct the baseball toward the middle of the screen  
BaseBalls(i%).x = -32
BaseBalls(i%).y = INT(RND * 230) - 32
BaseBalls(i%).yspeed = INT(RND * 3) + 1
IF BaseBalls(i%).y > 100 THEN BaseBalls(i%).yspeed = BaseBalls(i%).yspeed * -1
BaseBalls(i%).xspeed = INT(RND * 6) + 3
END SELECT
BaseBalls(i%).scnsd = sos% 'Remember where it came from
BaseBalls(i%).angle = INT(RND * 360) + 1 'Random angle of rotation
BaseBalls(i%).aspd = INT(RND * 15) + 1 'How fast it rotates
BaseBalls(i%).size = 128 + INT(RND * 512) + 1 'Pick a random size
'Pre-Calculate the center of rotaion
BaseBalls(i%).hts = 256 * ((BaseBalls(i%).size * 24) / 512 - 2)
EXIT FOR 'Were done here
END IF
NEXT i%
END IF

FOR i% = 1 TO maxballs%
IF BaseBalls(i%).exist = 1 THEN 'Does the baseball need attention
BaseBalls(i%).x = BaseBalls(i%).x + BaseBalls(i%).xspeed 'Add its xspeed to its x position
BaseBalls(i%).y = BaseBalls(i%).y + BaseBalls(i%).yspeed 'Add its yspeed to its y position
BaseBalls(i%).angle = BaseBalls(i%).angle + BaseBalls(i%).aspd 'Add its rotation speed to its angle
IF BaseBalls(i%).angle > 360 THEN BaseBalls(i%).angle = BaseBalls(i%).angle - 360 'keep the angle from going past 360
SELECT CASE BaseBalls(i%).scnsd 'Depedning on which side pf the screen it came from, kill it
CASE 1 'top
IF BaseBalls(i%).y > 200 THEN BaseBalls(i%).exist = 0
CASE 2 'right
IF BaseBalls(i%).x < -32 THEN BaseBalls(i%).exist = 0
CASE 3 'bottom
IF BaseBalls(i%).y < -32 THEN BaseBalls(i%).exist = 0
CASE 4 'left
IF BaseBalls(i%).x > 320 THEN BaseBalls(i%).exist = 0
END SELECT

'If its not dead by now, draw it to the screen using all its attributes
IF BaseBalls(i%).exist = 1 THEN DrawSprite BaseBalls(i%).x, BaseBalls(i%).y, BaseBalls(i%).angle, BaseBalls(i%).size, BaseBalls(i%).hts


END IF
NEXT i%


PCOPY 1, 2 'Refresh the screen
CLS 'Clear the screen

LOOP UNTIL INKEY$ <> ""
CLS
SYSTEM 'End the program


SpriteDat: 'Exactly what the label says (add an "a" at the end of Dat)
DATA 0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0
DATA 0,0,0,0,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0
DATA 0,0,0,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,3,0,0,0,0
DATA 0,0,4,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,3,2,5,0,0,0
DATA 0,1,4,4,4,1,2,2,1,2,2,1,2,2,1,1,2,3,3,5,2,2,0,0
DATA 0,1,1,4,5,3,3,2,3,1,1,3,2,2,3,1,3,5,2,3,1,2,0,0
DATA 1,1,1,1,1,3,2,3,5,5,3,5,5,3,5,5,1,3,1,1,2,2,2,0
DATA 1,1,2,2,2,1,2,1,3,2,2,3,2,2,3,2,2,1,2,2,2,2,2,0
DATA 1,1,2,2,2,2,2,2,1,2,2,1,2,2,1,2,2,2,2,2,2,1,1,0
DATA 1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,0
DATA 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,0
DATA 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,6,0
DATA 2,2,2,2,2,2,2,1,2,2,1,2,2,2,2,1,2,1,1,1,6,6,6,0
DATA 2,2,2,2,1,2,2,3,2,2,3,1,2,3,2,3,1,1,1,6,6,6,6,0
DATA 2,2,2,1,2,3,2,5,3,5,5,3,5,5,3,5,3,1,3,6,6,6,6,0
DATA 0,2,2,3,3,5,3,3,2,2,3,2,2,3,5,3,5,3,3,1,6,1,0,0
DATA 0,2,1,5,3,3,2,1,2,2,1,2,1,1,2,1,1,5,1,1,7,5,0,0
DATA 0,0,3,3,1,1,2,2,2,2,2,2,2,2,2,2,1,1,6,7,7,0,0,0
DATA 0,0,0,3,2,2,2,2,2,2,2,2,2,2,2,1,1,6,6,5,0,0,0,0
DATA 0,0,0,0,1,1,2,2,2,2,2,2,2,2,1,1,6,6,1,0,0,0,0,0
DATA 0,0,0,0,0,1,1,2,2,2,2,2,2,2,1,1,6,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,1,1,1,1,5,5,5,5,5,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

'Palette data
Pal:
DATA 8
DATA 63,0,63
DATA 56,56,32
DATA 63,62,60
DATA 56,16,16
DATA 56,40,32
DATA 48,55,48
DATA 48,48,48
DATA 32,0,0

SUB DrawSprite (x%, y%, angl%, sze%, htsd%)
ang% = 361 - angl% 'By default, this function rotates things counter
'clockwise

x1% = x%: y1% = y% 'Set the starting X position
x2% = x% + 31: y2% = y% + 31 'The window is 32 x 32 so add it to x1% and x2%
'and subtract 1 from 32 (31) to dimension it

Cx% = COSx%(ang%) 'Pre-calculate SIN value
Sx% = SINx%(ang%) 'Pre-calculate COS value

Xr% = (-15 * Cx% + 15 * Sx%) + htsd% 'Calculate Starting X rotation value and
'add the center of rotation to it
Yr% = (-15 * Sx% - 15 * Cx%) + htsd% 'Calculate Starting Y rotation value and
'add the center of rotation to it


ax2% = -Sx%: ay2% = Cx% 'Slopes for base values
ax1% = Cx%: ay1% = Sx% 'Slopes for main values

FOR yt% = y1% TO y2% 'Go from starting window coords to ending coords
u% = Xr%: v% = Yr% 'Reset u% and v%(similar to x% an y%) values for rotation
FOR xt% = x1% TO x2%

'divide u% and v% by scale% value to get the final pixel positions
xp% = u% / sze%
yp% = v% / sze%


'A little optimization that checks to see if the pixel to be plotted is
'past the right side of the sprite. It then skips over all the pixels (EXIT FOR)
'immmediatly to the right due to them being black and devoid
'of sprite data

IF yp% > 23 THEN

IF ang% < 180 THEN
EXIT FOR
END IF

ELSEIF xp% < 0 THEN

IF ang% > 90 AND ang% < 270 THEN
EXIT FOR
END IF


ELSEIF yp% < 0 THEN

IF ang% > 180 THEN
EXIT FOR
END IF


ELSEIF xp% > 23 THEN

IF ang% < 90 OR ang% > 270 THEN
EXIT FOR
END IF

ELSE

col% = Sprite%(xp%, yp%)
'If the pixel is the transparent color(1), dont plot it
IF col% <> 1 THEN PSET (xt%, yt%), col%
END IF

u% = u% + ax1% 'Add slopes to u% and v%
v% = v% + ay1%

NEXT xt%
Xr% = Xr% + ax2% 'Add base slopes to Xr% and Yr%
Yr% = Yr% + ay2%
NEXT yt%

END SUB

FUNCTION num$ (value%)
num$ = RIGHT$(STR$(value%), LEN(STR$(value%)) - 1)
END FUNCTION

SUB PutRGB (col%)
'Puts RCol, GCol, BCol values into the palette value "col"
IF setblack% = 0 THEN
OUT &H3C8, 0
OUT &H3C9, 0
OUT &H3C9, 0
OUT &H3C9, 0
setblack% = 1
END IF
OUT &H3C9, RCol%
OUT &H3C9, GCol%
OUT &H3C9, BCol%
END SUB
'-----------------------------------------------------------------------------
'_____________________________________________________________________________
It scans over the area of the screen where you want the rotated sprite to end up and reverts back to the original sprite to get the new pixels. It scales pretty nicely to. This is the fastest way I came up with to do scaling and rotating. Tell me what you think.
Mysoft
Posts: 836
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Post by Mysoft »

ya, thkz joshy

i have made one rotation code months ago, in my first try
with rotation but your code is about 4 times faster than mine
ahahahahaha

well thkz :)

zamaster, i haven't tested your code yet, but i will do soon.
Post Reply