roto-poly

Previous topic - Next topic

Scott_AW

Since I needed it, I made a rotatable polyvector function

Code (glbasic) Select

CREATESCREEN 1, 1,32,32
USESCREEN 1
DRAWRECT 0,0,16,16,RGB(255,0,0)
DRAWRECT 16,0,16,16,RGB(0,255,0)
DRAWRECT 0,16,16,16,RGB(0,0,255)
DRAWRECT 16,16,16,16,RGB(255,255,0)
USESCREEN -1
GLOBAL imh, imw

GETSPRITESIZE 1,imw,imh

LOCAL dir
WHILE KEY(1) = FALSE
  CLEARSCREEN RGB(0,0,0)
  rotopoly(dir,dir,dir)
  PRINT dir,0,0
  SHOWSCREEN

  IF dir < 360
    INC dir, 1
  ELSE
    dir = 0
  ENDIF
WEND
END

FUNCTION rotopoly: x, y, dir
  LOCAL w = imw/2, h = imh/2
  STARTPOLY 1, 2
    POLYVECTOR cast_x(x,w,dir+90), cast_y(y,h,dir+90), 0, 0, RGB(255,255,255)
    POLYVECTOR cast_x(x,-w,-dir+180), cast_y(y,h,-dir+180), 0, h*2, RGB(255,255,255)
    POLYVECTOR cast_x(x,w,-dir+180), cast_y(y,-h,-dir+180), w*2, 0, RGB(255,255,255)
    POLYVECTOR cast_x(x,w,dir-90), cast_y(y,h,dir-90), w*2, h*2, RGB(255,255,255)
  ENDPOLY
ENDFUNCTION

FUNCTION cast_x: x, dist, dir
  RETURN x+(COS(dir)*dist)
ENDFUNCTION

FUNCTION cast_y: y, dist, dir
  RETURN y+(SIN(dir)*dist)
ENDFUNCTION
Current Project, Orbital Contract Defense
http://gamejolt.com/games/adventure/code-name-ocd/9887/

BlackShadow now open source/resource(requires duke3d)
http://gamejolt.com/games/adventure/black-shadow-3d/9885/

Ian Price

I did something similar with my Guru Logic Champs game for Wiz. Came in very handy as one of the ROTO commands didn't work on the Wiz (can't remember exactly what now though).
I came. I saw. I played.

Minion

Scott, tried your piece of code, and while it is ok for square shapes, rectangles are not catered for ;(

Heres my code that I use for similar situations (Its a bit of a hack around of Gernots "Glowy Line" function) ....

Code (glbasic) Select

FUNCTION PolRot: x, y, w, h, rot, im, sx, sy, sw, sh

LOCAL tint1=RGB(255,255,255)
LOCAL tint2=RGB(255,255,255)

LOCAL scx=1,scy=1

LOCAL w,ddx,ddy,lg,dx,dy,ux,uy

LOCAL width=w
LOCAL width2=w/2
LOCAL height=h
LOCAL height2=h/2


LOCAL ly=(SIN(rot)*-(width2*scy))+y
LOCAL lx=(COS(rot)*-(width2*scx))+x

LOCAL ry=(SIN(rot)*(width2*scy))+y
LOCAL rx=(COS(rot)*(width2*scx))+x

LOCAL sz=height*scy


//line width
LOCAL w = sz

// direction of line
ddx = rx-lx
ddy = ry-ly
lg = SQR(ddx*ddx+ddy*ddy)
// IF lg>=0.5
//
// short caps
lg=lg*2
// dir vector
dx=ddx*w/lg
dy=ddy*w/lg
// up vector
ux=dy
uy=-dx

STARTPOLY im
POLYVECTOR lx+ux,  ly+uy,  sx,     sy,     tint1
POLYVECTOR lx-ux,  ly-uy,  sx,     sy+sh,  tint1
POLYVECTOR rx-ux,  ry-uy,  sx+sw,  sy+sh,  tint2
POLYVECTOR rx+ux,  ry+uy,  sx+sw,  sy,     tint2
ENDPOLY

ENDFUNCTION


I used this for my text routines so I could have a gradient look on my fonts. It also caters for scaling of the shape to (with the scx, scy vars)

Hope this is of hekp to somebody

Scott_AW

Thanks, I'll have to try that out.
Current Project, Orbital Contract Defense
http://gamejolt.com/games/adventure/code-name-ocd/9887/

BlackShadow now open source/resource(requires duke3d)
http://gamejolt.com/games/adventure/black-shadow-3d/9885/

Wampus

Well guys I couldn't get your code examples to work when I first tried (likely error on my part) so I re-invented the wheel.

I decided I wanted to replace all the Drawsprite style commands in my almost-ready iPhone game PowFish with polygons instead to get a bit of a performance boost. Problem is to get that performance boost all the sprites have to be on one single Texture Atlas. So, I wrote a small test routine to ape DRAWSPRITE, DRAWANIM and ROTOZOOMANIM - except using Polyvectors. The routine requires that the sprite co-ords and sizes are stored in an array but it otherwise works much the same as DRAWSPRITE, etc. The functions I defined were PolySprite, PolyAnim, PolyZoomAnim and PolyRotoZoomAnim.

As far as I know it works for any x,y sized sprite. The code for my PolyRotoZoomAnim looks hopelessly unoptimised in comparison to whatever it is that you guys are doing. I wouldn't know how to optimise it though. Luckily rotating sprites aren't often used in PowFish. Full source & sprites are included in a zip file.

Code (glbasic) Select
LOADSPRITE "playerstanding.png", 1                    // Just one sprite
LOADANIM "playerwalking.png", 2, 32, 64            // Animation frames are 32 by 64

LOADSPRITE "textureatlas.png", 20                        // The texture atlas for use with Polyvector


GLOBAL sprites[]                                // Array to hold sprite details in
DIM sprites[3][12][4]                        // sprite [sprite number] [animation frame] [x co-ords, y co-ords, x width, y height]

GLOBAL drawmethod = 0                        // 0 = drawsprite mode, 1 = Polyvector mode
GLOBAL an = 0                                // anim character walking from 0 to 11
GLOBAL animdelay = 0                        // delay in animation frames
GLOBAL ang = 0                            // Angle to draw sprite at
GLOBAL sca = 1                            // scale of sprite
GLOBAL scadelay = 0
GLOBAL drawdelay = 0                        // used to flip between Drawsprite and Polyvector

GLOBAL sine[]                            // precalculate sine and cosine
GLOBAL cosine[]
DIM sine[360]
DIM cosine[360]



// variables for use with the PolySprite functions

GLOBAL patx, paty, patxx, patyy, porwidth, porheight, porcentx, porcenty, pwidth, pheight, pcentx, pcenty
GLOBAL pltx, plty, plbx, plby, prtx, prty, prbx, prby, pcolour, pminx, pminy, pmaxx, pmaxy


// Initialise this example

SetupSpriteData()
PrecalculateAngles()



// Main Loop

WHILE KEY(01) = FALSE

    IF drawmethod = 0
   
        ALPHAMODE -1.0
       
        DRAWSPRITE 1, 96, 128
   
        DRAWANIM 2, an, 224, 128
       
        ROTOZOOMANIM 2, an, 352, 128, 0, sca
       
        ROTOZOOMANIM 2, an, 480, 128, ang, sca
       
        PRINT "DRAWSPRITE style", 235, 40
       
       
   
    ELSEIF drawmethod = 1
   
        ALPHAMODE -1.0
   
        STARTPOLY 20, 1
       
        PolySprite(1, 96, 128)
       
        PolyAnim(2, an, 224, 128)
       
        PolyZoomAnim(2, an, 352, 128, sca)
       
        PolyRotoZoomAnim(2, an, 480, 128, ang, sca)       
       
        ENDPOLY
       
        PRINT "Polysprite function calls", 205, 40
       
   
    ENDIF
   
   
    INC animdelay
   
    IF animdelay = 4
        animdelay = 0
        INC an
        IF an = 12 THEN an = 0
    ENDIF   
   
   
    INC ang
    IF ang = 360 THEN ang = 0
   
   
    INC drawdelay
    IF drawdelay = 120 THEN drawmethod = 1
    IF drawdelay = 240
        drawmethod = 0
        drawdelay = 0
    ENDIF
   
    INC scadelay
    IF scadelay >= 360 THEN scadelay = 0
    sca = 2-sine[scadelay]

   
   
   
   
    SHOWSCREEN
   
WEND



// End the program
END
// End the program




FUNCTION PolySprite: sprite, minx, miny

patx = sprites[sprite][0][0]
paty = sprites[sprite][0][1]
patxx = sprites[sprite][0][0]+sprites[sprite][0][2]
patyy = sprites[sprite][0][1]+sprites[sprite][0][3]
pminx = minx
pminy = miny
pmaxx = pminx+sprites[sprite][0][2]
pmaxy = pminy+sprites[sprite][0][3]


pcolour = RGB(255, 255, 255)


POLYVECTOR pminx, pminy, patx, paty, pcolour
POLYVECTOR pminx, pmaxy, patx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour

POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pminy, patxx, paty, pcolour
POLYVECTOR pminx, pminy, patx, paty, pcolour

ENDFUNCTION







FUNCTION PolyAnim: sprite, frame, minx, miny

patx = sprites[sprite][frame][0]
paty = sprites[sprite][frame][1]
patxx = sprites[sprite][frame][0]+sprites[sprite][frame][2]
patyy = sprites[sprite][frame][1]+sprites[sprite][frame][3]
pminx = minx
pminy = miny
pmaxx = pminx+sprites[sprite][frame][2]
pmaxy = pminy+sprites[sprite][frame][3]


pcolour = RGB(255, 255, 255)


POLYVECTOR pminx, pminy, patx, paty, pcolour
POLYVECTOR pminx, pmaxy, patx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour

POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pminy, patxx, paty, pcolour
POLYVECTOR pminx, pminy, patx, paty, pcolour

ENDFUNCTION





FUNCTION PolyZoomAnim: sprite, frame, xpos, ypos, scale

patx = sprites[sprite][frame][0]
paty = sprites[sprite][frame][1]
patxx = sprites[sprite][frame][0]+sprites[sprite][frame][2]
patyy = sprites[sprite][frame][1]+sprites[sprite][frame][3]


porwidth = sprites[sprite][frame][2]
porheight = sprites[sprite][frame][3]
pwidth = sprites[sprite][frame][2] * scale
pheight = sprites[sprite][frame][3] * scale


porcentx = porwidth / 2
porcenty = porheight / 2
pcentx = pwidth / 2
pcenty = pheight / 2


pminx = xpos + (porcentx - pcentx)
pminy = ypos + (porcenty - pcenty)
pmaxx = xpos + (porcentx + pcentx)
pmaxy = ypos + (porcenty + pcenty)


pcolour = RGB(255, 255, 255)


POLYVECTOR pminx, pminy, patx, paty, pcolour
POLYVECTOR pminx, pmaxy, patx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour

POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pminy, patxx, paty, pcolour
POLYVECTOR pminx, pminy, patx, paty, pcolour

ENDFUNCTION









FUNCTION PolyRotoZoomAnim: sprite, frame, xpos, ypos, angle, scale

angle = 359 - angle


patx = sprites[sprite][frame][0]
paty = sprites[sprite][frame][1]
patxx = sprites[sprite][frame][0]+sprites[sprite][frame][2]
patyy = sprites[sprite][frame][1]+sprites[sprite][frame][3]


porwidth = sprites[sprite][frame][2]
porheight = sprites[sprite][frame][3]
pwidth = sprites[sprite][frame][2] * scale
pheight = sprites[sprite][frame][3] * scale


porcentx = porwidth / 2
porcenty = porheight / 2
pcentx = pwidth / 2
pcenty = pheight / 2


pminx = -porcentx
pminy = -porcenty
pmaxx = porcentx
pmaxy = porcenty


pltx = ((cosine[angle]*pminx) - (sine[angle]*pminy)) * scale
plty = ((sine[angle]*pminx) + (cosine[angle]*pminy)) * scale

plbx = ((cosine[angle]*pminx) - (sine[angle]*pmaxy)) * scale
plby = ((sine[angle]*pminx) + (cosine[angle]*pmaxy)) * scale

prtx = ((cosine[angle]*pmaxx) - (sine[angle]*pminy)) * scale
prty = ((sine[angle]*pmaxx) + (cosine[angle]*pminy)) * scale

prbx = ((cosine[angle]*pmaxx) - (sine[angle]*pmaxy)) * scale
prby = ((sine[angle]*pmaxx) + (cosine[angle]*pmaxy)) * scale

xpos = xpos + porcentx
ypos = ypos + porcenty


pltx = xpos + pltx
plty = ypos + plty
plbx = xpos + plbx
plby = ypos + plby
prtx = xpos + prtx
prty = ypos + prty
prbx = xpos + prbx
prby = ypos + prby


pcolour = RGB(255, 255, 255)


POLYVECTOR pltx, plty, patx, paty, pcolour
POLYVECTOR plbx, plby, patx, patyy, pcolour
POLYVECTOR prbx, prby, patxx, patyy, pcolour

POLYVECTOR prbx, prby, patxx, patyy, pcolour
POLYVECTOR prtx, prty, patxx, paty, pcolour
POLYVECTOR pltx, plty, patx, paty, pcolour

ENDFUNCTION










FUNCTION PrecalculateAngles:

FOR i = 0 TO 359

    sine[i] = SIN(i)
    cosine[i] = COS(i)

NEXT

ENDFUNCTION





FUNCTION SetupSpriteData:
   
    //    Set up sprite data for use to simulate Drawsprite-like function calls //
   
    RESTORE spritestuff
   
    READ sprites[1][0][0]
    READ sprites[1][0][1]
    READ sprites[1][0][2]
    READ sprites[1][0][3]
   
    FOR i = 0 TO 11
   
        READ sprites[2][i][0]
        READ sprites[2][i][1]
        READ sprites[2][i][2]
        READ sprites[2][i][3]
       
    NEXT
   
ENDFUNCTION
   




// Start of sprite data. Clumsy but I couldn't be bothered to store this information in a file just for this test routine
   
STARTDATA spritestuff:
   
    DATA 128, 64, 32, 64            // sprite 1: start x co-ord, start y co-ord, x width, y height
   
    DATA 0, 0, 32, 64                // sprite 2, anim-number 0: start x co-ord, start y co-ord, x width, y height
    DATA 32, 0, 32, 64                // sprite 2, anim-number 1: start x co-ord, start y co-ord, x width, y height
    DATA 64, 0, 32, 64                // sprite 2, anim-number 2: start x co-ord, start y co-ord, x width, y height
    DATA 96, 0, 32, 64                // sprite 2, anim-number 3: start x co-ord, start y co-ord, x width, y height
    DATA 128, 0, 32, 64                // sprite 2, anim-number 4: start x co-ord, start y co-ord, x width, y height
    DATA 160, 0, 32, 64                // sprite 2, anim-number 5: start x co-ord, start y co-ord, x width, y height
    DATA 192, 0, 32, 64                // sprite 2, anim-number 6: start x co-ord, start y co-ord, x width, y height
    DATA 224, 0, 32, 64                // sprite 2, anim-number 7: start x co-ord, start y co-ord, x width, y height
    DATA 256, 0, 32, 64                // sprite 2, anim-number 8: start x co-ord, start y co-ord, x width, y height
    DATA 288, 0, 32, 64                // sprite 2, anim-number 9: start x co-ord, start y co-ord, x width, y height
    DATA 0, 64, 32, 64                // sprite 2, anim-number 10: start x co-ord, start y co-ord, x width, y height
    DATA 32, 64, 32, 64                // sprite 2, anim-number 11: start x co-ord, start y co-ord, x width, y height
       
ENDDATA


[attachment deleted by admin]

Ian Price

Had a quick look and it does exactly what it says on the tin :)

Have you compared the drawspeed when you've got hundreds of these polyvectors vs sprites?  Is there a substantial difference? I'll have a play later.

I did something similar for my Blitz iPod game and got a massive increase in speed, so I'm expecting likewise.
I came. I saw. I played.

Scott_AW

Nicely done, putting the sin and cos in arrays should cut down on processing a little.

As far as I've experienced, if you use polyvector correctly you can put a bunch of stuff on the screen where the sprite commands may lag.
Current Project, Orbital Contract Defense
http://gamejolt.com/games/adventure/code-name-ocd/9887/

BlackShadow now open source/resource(requires duke3d)
http://gamejolt.com/games/adventure/black-shadow-3d/9885/

Wampus

#7
Ian, I have a benchmarking app I wrote specifically for testing the difference between drawsprite and the different polyvector modes (and variables). My experiments with that led me to conclude Polyvector is always faster and that once you're into drawing hundreds of sprites the Polyvector Triangle or Strip method is practically essential.

I could upload the benchmarking app if people would like it. It might be interesting to see what kind of performance differences people get on different devices. At the moment I just have an iPod Touch (3GS equivalent) to test it with.

(edit: I have yet to test the PolySprite functions I wrote to see how much faster they might be on the iPhone. However, I don't think I'm going to do that. I'm going to be dangerous and just assume they'll be faster. I'll know once I've had the time to update PowFish with them.)

Ian Price

Quoteconclude Polyvector is always faster and that once you're into drawing hundreds of sprites the Polyvector Triangle or Strip method is practically essential.

My tests confirm this too; as I stated -
QuoteI did something similar for my Blitz iPod game and got a massive increase in speed, so I'm expecting likewise.

I'm using POLYVECTOR in pretty much everything now.

:)
I came. I saw. I played.

Scott_AW

The only issues I've experienced is when systems have old drivers or don't support OpenGL, then things crawl or are horribly distorted.

I've also had trouble with creating trapezoids, either my vector order is off or something, but the textures don't bend correctly.
Current Project, Orbital Contract Defense
http://gamejolt.com/games/adventure/code-name-ocd/9887/

BlackShadow now open source/resource(requires duke3d)
http://gamejolt.com/games/adventure/black-shadow-3d/9885/