eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › how 2 speed up rotozoomer
Ilość wypowiedzi w tym wątku: 2

  • 1. Data: 2017-09-30 23:48:03
    Temat: how 2 speed up rotozoomer
    Od: fir <p...@g...com>

    rotozumer is a routine that displays bitmap
    on screen (which is also a bitmap so this is like
    copying bitmap onto bitmap) but the input bitmap
    (you may call it 'sprite') will be rotated by given angle and scaled by given zoom

    the method is just to iterate on spirite all pixels, totate them (this is multiply by
    rotated base vectors that
    sescribes rotation and zoom) and set this roteted zoomed pixels to screen (yet if
    zoom is like 2.0 the sampling of the input should be not by +1 step but more like
    +0.5 to not make holes in output)

    my unoptymised and not much edited for names etc function for this is that

    inline void Rotate2d(float* x, float* y, float angle)
    {
    float xt = (*x) * cos(angle*degree360) - (*y) * sin(angle*degree360);
    float yt = (*x) * sin(angle*degree360) + (*y) * cos(angle*degree360);

    *x = xt;
    *y = yt;
    }


    void DrawSprite2(float pos_x,
    float pos_y,
    char* file,
    int sprite_bitmap_pos_x,
    int sprite_bitmap_pos_y,
    int sprite_bitmap_end_x,
    int sprite_bitmap_end_y,
    float angle = 0 ,
    float zoom = 1,
    int sprite_centre_bitmap_x = -1,
    int sprite_centre_bitmap_y = -1

    )

    {

    if(sprite_centre_bitmap_x<0 || sprite_centre_bitmap_y<0)
    {
    sprite_centre_bitmap_x = (sprite_bitmap_pos_x + sprite_bitmap_end_x)/2;
    sprite_centre_bitmap_y = (sprite_bitmap_pos_y + sprite_bitmap_end_y)/2;

    }


    float sprite_width = sprite_bitmap_end_x - sprite_bitmap_pos_x + 1 ;
    float sprite_height = sprite_bitmap_end_y - sprite_bitmap_pos_y + 1;



    float Ax = sprite_bitmap_pos_x - sprite_centre_bitmap_x ;
    float Ay = sprite_bitmap_pos_y - sprite_centre_bitmap_y ;
    float Bx = sprite_bitmap_end_x - sprite_centre_bitmap_x ;
    float By = sprite_bitmap_pos_y - sprite_centre_bitmap_y ;
    float Cx = sprite_bitmap_end_x - sprite_centre_bitmap_x ;
    float Cy = sprite_bitmap_end_y - sprite_centre_bitmap_y ;
    float Dx = sprite_bitmap_pos_x - sprite_centre_bitmap_x ;
    float Dy = sprite_bitmap_end_y - sprite_centre_bitmap_y ;

    Rotate2d(&Ax,&Ay, angle);
    Rotate2d(&Bx,&By, angle);
    // Rotate2d(&Cx,&Cy, angle);
    Rotate2d(&Dx,&Dy, angle);


    float dxdx = (Bx-Ax)/sprite_width;
    float dydx = (By-Ay)/sprite_width;

    float dxdy = (Dx-Ax)/sprite_height;
    float dydy = (Dy-Ay)/sprite_height;

    float x, y;


    for(float j=sprite_bitmap_pos_y-sprite_centre_bitmap_y;
    j<sprite_bitmap_end_y-sprite_centre_bitmap_y; j+=.7/zoom)
    {
    for(float i=sprite_bitmap_pos_x-sprite_centre_bitmap_x;
    i<sprite_bitmap_end_x-sprite_centre_bitmap_x; i+=.7/zoom)
    {
    unsigned color = sprites_buf_[sprite_centre_bitmap_y +
    int(j)][sprite_centre_bitmap_x + int(i)];

    x = 0*sprite_centre_bitmap_x + i * dxdx*zoom + j*dxdy*zoom;
    y = 0*sprite_centre_bitmap_y + i * dydx*zoom + j*dydy*zoom;

    if(color==0) {} else SetPixelSafe(pos_x + x, pos_y + y, color);


    }
    }


    }


    the problem is clipping, if sprite is rotated positioned and zoomed often quite large
    parts and a lot of pixels destinate out the screen - and here in that routine i clib
    them all per pixel (in "SetPixelSafe")

    this is much wastefull, and optimistation of this routine is very important as
    sprites, esp big sprites or sprites that are zoomed to be big may take real lot of
    time on cpu
    (rotozuming big screen size or overscreen sprites sadly may take like 40 ms which is
    deadly slow (where small ones may take like 1 ms which is ok)

    so how to speed it up?
    (id someone want to see how it runs i may ulpoad te win32 exe showing how it worx)


  • 2. Data: 2017-10-01 11:51:04
    Temat: Re: how 2 speed up rotozoomer
    Od: fir <p...@g...com>

    W dniu sobota, 30 września 2017 23:48:04 UTC+2 użytkownik fir napisał:
    > rotozumer is a routine that displays bitmap
    > on screen (which is also a bitmap so this is like
    > copying bitmap onto bitmap) but the input bitmap
    > (you may call it 'sprite') will be rotated by given angle and scaled by given zoom
    >
    > the method is just to iterate on spirite all pixels, totate them (this is multiply
    by rotated base vectors that
    > sescribes rotation and zoom) and set this roteted zoomed pixels to screen (yet if
    zoom is like 2.0 the sampling of the input should be not by +1 step but more like
    +0.5 to not make holes in output)
    >
    > my unoptymised and not much edited for names etc function for this is that
    >
    > inline void Rotate2d(float* x, float* y, float angle)
    > {
    > float xt = (*x) * cos(angle*degree360) - (*y) * sin(angle*degree360);
    > float yt = (*x) * sin(angle*degree360) + (*y) * cos(angle*degree360);
    >
    > *x = xt;
    > *y = yt;
    > }
    >
    >
    > void DrawSprite2(float pos_x,
    > float pos_y,
    > char* file,
    > int sprite_bitmap_pos_x,
    > int sprite_bitmap_pos_y,
    > int sprite_bitmap_end_x,
    > int sprite_bitmap_end_y,
    > float angle = 0 ,
    > float zoom = 1,
    > int sprite_centre_bitmap_x = -1,
    > int sprite_centre_bitmap_y = -1
    >
    > )
    >
    > {
    >
    > if(sprite_centre_bitmap_x<0 || sprite_centre_bitmap_y<0)
    > {
    > sprite_centre_bitmap_x = (sprite_bitmap_pos_x + sprite_bitmap_end_x)/2;

    > sprite_centre_bitmap_y = (sprite_bitmap_pos_y + sprite_bitmap_end_y)/2;

    >
    > }
    >
    >
    > float sprite_width = sprite_bitmap_end_x - sprite_bitmap_pos_x + 1 ;
    > float sprite_height = sprite_bitmap_end_y - sprite_bitmap_pos_y + 1;
    >
    >
    >
    > float Ax = sprite_bitmap_pos_x - sprite_centre_bitmap_x ;
    > float Ay = sprite_bitmap_pos_y - sprite_centre_bitmap_y ;
    > float Bx = sprite_bitmap_end_x - sprite_centre_bitmap_x ;
    > float By = sprite_bitmap_pos_y - sprite_centre_bitmap_y ;
    > float Cx = sprite_bitmap_end_x - sprite_centre_bitmap_x ;
    > float Cy = sprite_bitmap_end_y - sprite_centre_bitmap_y ;
    > float Dx = sprite_bitmap_pos_x - sprite_centre_bitmap_x ;
    > float Dy = sprite_bitmap_end_y - sprite_centre_bitmap_y ;
    >
    > Rotate2d(&Ax,&Ay, angle);
    > Rotate2d(&Bx,&By, angle);
    > // Rotate2d(&Cx,&Cy, angle);
    > Rotate2d(&Dx,&Dy, angle);
    >
    >
    > float dxdx = (Bx-Ax)/sprite_width;
    > float dydx = (By-Ay)/sprite_width;
    >
    > float dxdy = (Dx-Ax)/sprite_height;
    > float dydy = (Dy-Ay)/sprite_height;
    >
    > float x, y;
    >
    >
    > for(float j=sprite_bitmap_pos_y-sprite_centre_bitmap_y;
    j<sprite_bitmap_end_y-sprite_centre_bitmap_y; j+=.7/zoom)
    > {
    > for(float i=sprite_bitmap_pos_x-sprite_centre_bitmap_x;
    i<sprite_bitmap_end_x-sprite_centre_bitmap_x; i+=.7/zoom)
    > {
    > unsigned color = sprites_buf_[sprite_centre_bitmap_y +
    int(j)][sprite_centre_bitmap_x + int(i)];
    >
    > x = 0*sprite_centre_bitmap_x + i * dxdx*zoom + j*dxdy*zoom;
    > y = 0*sprite_centre_bitmap_y + i * dydx*zoom + j*dydy*zoom;
    >
    > if(color==0) {} else SetPixelSafe(pos_x + x, pos_y + y, color);
    >
    >
    > }
    > }
    >
    >
    > }
    >
    >
    > the problem is clipping, if sprite is rotated positioned and zoomed often quite
    large parts and a lot of pixels destinate out the screen - and here in that routine i
    clib them all per pixel (in "SetPixelSafe")
    >
    > this is much wastefull, and optimistation of this routine is very important as
    sprites, esp big sprites or sprites that are zoomed to be big may take real lot of
    time on cpu
    > (rotozuming big screen size or overscreen sprites sadly may take like 40 ms which
    is deadly slow (where small ones may take like 1 ms which is ok)
    >
    > so how to speed it up?
    > (id someone want to see how it runs i may ulpoad te win32 exe showing how it worx)

    example

    minddetonator.htw.pl/rotozoomer.zip

    (this is this above version - non optimised one)

    in fact it is seen i in fact see the way of improvin it

    it seems it should be able to reduce this to:


    for(n)
    {
    sx += dsx;

    color = sprite[sy][sx]

    x += dx;
    y += dy;
    //where one of this dx dy could be 1.0

    StePixel(x,y, color);
    }

    for each given scanline ( this scanline is just one vertical row of pixels from
    input sprite )

    setup values for x,y and n and deltac could be count just from cliping line to 2d
    screen i think

    yet some specyfic is if sprite is bigly soomed each one pixel in input sprite could
    be read many times the same value - this could be also optimised but this is a bit
    hardcore

    sad news is i dont know if i do feel like to code this above now ;c;c **

    good news is i not touched such perpixel algorithmics for some like 3 years and now i
    see i generally see this things yet clearer and could give to myself one additional
    mastery token in that field as i think i see (in fact i see those algorithms clearer)


    ** in fact i SHOULD do this 2d screen line clipping
    (shouldnt be to hard but i feel to weak) i will see

strony : [ 1 ]


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: