PDA

View Full Version : Speeding up a rotate/alpha routine



WILL
05-09-2004, 07:09 AM
ok boys, here's the code. I have yet to find a ay of increading the speed on this bad-boy beyond using the cos/sin lookup tables and moving the

RX := SX - OX;
RY := SY - OY;
NX := Round(mx + RX * aSin + RY * aCos); //
NY := Round(my + RY * aSin - RX * aCos); //
portion inside of the

if ((DX > 0) and (DX < MAXX)) and
((DY > 0) and (DY < MAXY)) then
begin
conditional statement.



Have a look and let me know what you think:

procedure SDL_RotateDeg_Alpha3(DstSurface, SrcSurface: PSDL_Surface; SrcRect: PSDL_Rect;
DestX, DestY, OffsetX, OffsetY: Integer; Angle: Integer;
Alpha: UInt8);
var
aSin, aCos: Single;
MX, MY, DX, DY, NX, NY, SX, SY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY: Integer;
SrcColor, DstColor: UInt32;
srcRR, srcGG, srcBB, dstRR, dstGG, dstBB: UInt8;
Color, TempTransparentColour: UInt32;
MAXX, MAXY: Integer;

begin
// Rotate the surface to the target surface.
TempTransparentColour := SrcSurface.format.colorkey;
if (srcRect.w > srcRect.h) then
begin
Width := srcRect.w;
Height := srcRect.w;
end
else
begin
Width := srcRect.h;
Height := srcRect.h;
end;

maxx := DstSurface.w;
maxy := DstSurface.h;
aCos := degCOS[Angle];
aSin := degSIN[Angle];

Width := round(abs(srcrect.h * acos) + abs(srcrect.w * asin));
Height := round(abs(srcrect.h * asin) + abs(srcrect.w * acos));

OX := Width shr 1;
OY := Height shr 1;
MX := (srcRect.x + (srcRect.x + srcRect.w)) shr 1;
MY := (srcRect.y + (srcRect.y + srcRect.h)) shr 1;
ROX := (-(srcRect.w shr 1)) + Offsetx;
ROY := (-(srcRect.h shr 1)) + OffsetY;
Tx := ox + round(ROX * aSin - ROY * aCos);
Ty := oy + round(ROY * aSin + ROX * aCos);
SX := 0;
for DX := DestX - TX to DestX - TX + (width) do
begin
inc(SX);
SY := 0;
for DY := DestY - TY to DestY - TY + (Height) do
begin
if ((DX > 0) and (DX < MAXX)) and
((DY > 0) and (DY < MAXY)) then
begin
RX := SX - OX;
RY := SY - OY;
NX := mx + Round(RX * aSin + RY * aCos); //
NY := my + Round(RY * aSin - RX * aCos); //

// Used for testing only
//SDL_PutPixel(DestSurface.SDLSurfacePointer,DX,DY,0 );

if (NX >= srcRect.x) and (NX <= srcRect.x + srcRect.w) then
begin
if (NY >= srcRect.y) and (NY <= srcRect.y + srcRect.h) then
begin
SrcColor := SDL_GetPixel(SrcSurface, NX, NY);
if (SrcColor <> TempTransparentColour) then
begin
SDL_GetRGB(SrcColor, SrcSurface.format, @srcRR, @srcGG, @srcBB);

DstColor := SDL_GetPixel(DstSurface, DX, DY);
SDL_GetRGB(DstColor, DstSurface.format, @dstRR, @dstGG, @dstBB);

Color := SDL_MapRGB(DstSurface.format,
Round((Alpha * (srcRR - dstRR)) shr 8 + dstRR),
Round((Alpha * (srcGG - dstGG)) shr 8 + dstGG),
Round((Alpha * (srcBB - dstBB)) shr 8 + dstBB));

SDL_PutPixel(DstSurface, DX, DY, Color);
end;
end;
end;
end;
inc(SY);
end;
end;
end;

Paulius
05-09-2004, 03:33 PM
You should switch X and Y loop places to make memory access more sequential. As rounding is not fast, you could make aSin and aCos into integers (to give them some resolution multiply them by a power of two before rounding and then in loops just use shifts). You should also consider inlineing those SDL functions, and maybe also assume some limitations like not supporting 8bit color.