hedgewars/uRender.pas
branchqmlfrontend
changeset 12860 1b2b84315d27
parent 11833 a69124eb7ce7
parent 12626 d972b31f8881
child 12883 b3426030a426
equal deleted inserted replaced
11848:01f88c3b7b66 12860:1b2b84315d27
    32 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
    32 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
    33 procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline;
    33 procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline;
    34 procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
    34 procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
    35 procedure DrawSpriteRotated     (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
    35 procedure DrawSpriteRotated     (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
    36 procedure DrawSpriteRotatedF    (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
    36 procedure DrawSpriteRotatedF    (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
       
    37 procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
    37 
    38 
    38 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture); inline;
    39 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture); inline;
    39 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
    40 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
    40 procedure DrawTexture2          (X, Y: LongInt; Texture: PTexture; Scale, Overlap: GLfloat);
    41 procedure DrawTexture2          (X, Y: LongInt; Texture: PTexture; Scale, Overlap: GLfloat);
    41 procedure DrawTextureFromRect   (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline;
    42 procedure DrawTextureFromRect   (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline;
    71 
    72 
    72 // call this to finish the rendering of current frame
    73 // call this to finish the rendering of current frame
    73 procedure FinishRender();
    74 procedure FinishRender();
    74 
    75 
    75 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
    76 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
       
    77 function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline;
    76 
    78 
    77 // 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen
    79 // 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen
    78 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
    80 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
    79 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline;
    81 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline;
    80 
    82 
   101 procedure openglPopMatrix       (); inline;
   103 procedure openglPopMatrix       (); inline;
   102 procedure openglTranslatef      (X, Y, Z: GLfloat); inline;
   104 procedure openglTranslatef      (X, Y, Z: GLfloat); inline;
   103 
   105 
   104 
   106 
   105 implementation
   107 implementation
   106 uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils, uConsts
   108 uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils
   107      {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uPhysFSLayer, uDebug;
   109      {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uConsts;
   108 
   110 
   109 {$IFDEF USE_TOUCH_INTERFACE}
   111 {$IFDEF USE_TOUCH_INTERFACE}
   110 const
   112 const
   111     FADE_ANIM_TIME = 500;
   113     FADE_ANIM_TIME = 500;
   112     MOVE_ANIM_TIME = 500;
   114     MOVE_ANIM_TIME = 500;
   143 {$ENDIF}
   145 {$ENDIF}
   144 
   146 
   145 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
   147 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
   146 begin
   148 begin
   147     isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
   149     isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
       
   150 end;
       
   151 
       
   152 function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline;
       
   153 var dRightX, dBottomY, dLeftX, dTopY: LongInt;
       
   154 begin
       
   155     dRightX:= (X - ViewRightX);
       
   156     dBottomY:= (Y - ViewBottomY);
       
   157     dLeftX:= (ViewLeftX - X);
       
   158     dTopY:= (ViewTopY - Y);
       
   159     isCircleOffscreen:= 
       
   160         ((dRightX > 0) and (sqr(dRightX) > RadiusSquared)) or
       
   161         ((dBottomY > 0) and (sqr(dBottomY) > RadiusSquared)) or
       
   162         ((dLeftX > 0) and (sqr(dLeftX) > RadiusSquared)) or
       
   163         ((dTopY > 0) and (sqr(dTopY) > RadiusSquared))
   148 end;
   164 end;
   149 
   165 
   150 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
   166 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
   151 begin
   167 begin
   152     if X > ViewRightX then exit(1);
   168     if X > ViewRightX then exit(1);
  1129 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
  1145 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
  1130 begin
  1146 begin
  1131 
  1147 
  1132 if Angle <> 0  then
  1148 if Angle <> 0  then
  1133     begin
  1149     begin
  1134     // sized doubled because the sprite might occupy up to 1.4 * of it's
  1150     // Check the bounding circle 
  1135     // original size in each dimension, because it is rotated
  1151     if isCircleOffscreen(X, Y, sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) then
  1136     if isDxAreaOffscreen(X - SpritesData[Sprite].Width, 2 * SpritesData[Sprite].Width) <> 0 then
       
  1137         exit;
       
  1138     if isDYAreaOffscreen(Y - SpritesData[Sprite].Height, 2 * SpritesData[Sprite].Height) <> 0 then
       
  1139         exit;
  1152         exit;
  1140     end
  1153     end
  1141 else
  1154 else
  1142     begin
  1155     begin
  1143     if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then
  1156     if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then
  1160 
  1173 
  1161 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
  1174 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
  1162 
  1175 
  1163 openglPopMatrix;
  1176 openglPopMatrix;
  1164 
  1177 
       
  1178 end;
       
  1179 
       
  1180 procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
       
  1181 begin
       
  1182 if Angle <> 0  then
       
  1183     begin
       
  1184     // Check the bounding circle 
       
  1185     // Assuming the pivot point is inside the sprite's rectangle, the farthest possible point is 3/2 of its diagonal away from the center
       
  1186     if isCircleOffscreen(X, Y, 9 * (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then
       
  1187         exit;
       
  1188     end
       
  1189 else
       
  1190     begin
       
  1191     if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then
       
  1192         exit;
       
  1193     if isDYAreaOffscreen(Y - SpritesData[Sprite].Height div 2 , SpritesData[Sprite].Height) <> 0 then
       
  1194         exit;
       
  1195     end;
       
  1196 
       
  1197 openglPushMatrix;
       
  1198 openglTranslatef(X, Y, 0);
       
  1199 
       
  1200 // mirror
       
  1201 if Dir < 0 then
       
  1202     openglScalef(-1.0, 1.0, 1.0);
       
  1203 
       
  1204 // apply rotation around the pivot after (conditional) mirroring
       
  1205 if Angle <> 0  then
       
  1206     begin
       
  1207     openglTranslatef(PivotX, PivotY, 0);
       
  1208     openglRotatef(Angle, 0, 0, 1);
       
  1209     openglTranslatef(-PivotX, -PivotY, 0);
       
  1210     end;
       
  1211 
       
  1212 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
       
  1213 
       
  1214 openglPopMatrix;
  1165 end;
  1215 end;
  1166 
  1216 
  1167 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
  1217 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
  1168 begin
  1218 begin
  1169 
  1219 
  1731 glColor4ub($FF, $FF, $FF, $FF);
  1781 glColor4ub($FF, $FF, $FF, $FF);
  1732 {$ENDIF}
  1782 {$ENDIF}
  1733 end;
  1783 end;
  1734 
  1784 
  1735 procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
  1785 procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
  1736 var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt;
  1786 var first, count, topy, lx, rx, spriteHeight, spriteWidth, waterSpeed: LongInt;
  1737     lw, nWaves, shift: GLfloat;
  1787     waterFrames, waterFrameTicks, frame : LongWord;
       
  1788     lw, nWaves, shift, realHeight: GLfloat;
  1738     sprite: TSprite;
  1789     sprite: TSprite;
  1739 begin
  1790 begin
  1740 // note: spriteHeight is the Height of the wave sprite while
  1791 // note: spriteHeight is the Height of the wave sprite while
  1741 //       cWaveHeight describes how many pixels of it will be above waterline
  1792 //       cWaveHeight describes how many pixels of it will be above waterline
  1742 
  1793 
  1743 if SuddenDeathDmg then
  1794 if SuddenDeathDmg then
  1744     sprite:= sprSDWater
  1795     begin
       
  1796     sprite:= sprSDWater;
       
  1797     waterFrames:= watSDFrames;
       
  1798     waterFrameTicks:= watSDFrameTicks;
       
  1799     waterSpeed:= watSDMove;
       
  1800     end
  1745 else
  1801 else
       
  1802     begin
  1746     sprite:= sprWater;
  1803     sprite:= sprWater;
  1747 
  1804     waterFrames:= watFrames;
       
  1805     waterFrameTicks:= watFrameTicks;
       
  1806     waterSpeed:= watMove;
       
  1807     end;
       
  1808  
  1748 spriteHeight:= SpritesData[sprite].Height;
  1809 spriteHeight:= SpritesData[sprite].Height;
       
  1810 realHeight:= SpritesData[sprite].Texture^.ry / waterFrames;
  1749 
  1811 
  1750 // shift parameters by wave height
  1812 // shift parameters by wave height
  1751 // ( ox and dy are used to create different horizontal and vertical offsets
  1813 // ( ox and dy are used to create different horizontal and vertical offsets
  1752 //   between wave layers )
  1814 //   between wave layers )
  1753 dY:= -cWaveHeight + dy;
  1815 dY:= -cWaveHeight + dy;
  1804 
  1866 
  1805 spriteWidth:= SpritesData[sprite].Width;
  1867 spriteWidth:= SpritesData[sprite].Width;
  1806 nWaves:= lw / spriteWidth;
  1868 nWaves:= lw / spriteWidth;
  1807     shift:= - nWaves / 2;
  1869     shift:= - nWaves / 2;
  1808 
  1870 
  1809 TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
  1871 if waterFrames > 1 then
  1810 TextureBuffer[3].Y:= 0;
  1872 	frame:= RealTicks div waterFrameTicks mod waterFrames
       
  1873 else
       
  1874 	frame:= 0;
       
  1875 
       
  1876 TextureBuffer[3].X:= shift + ((LongInt((RealTicks * waterSpeed div 100) shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
       
  1877 TextureBuffer[3].Y:= frame * realHeight;
  1811 TextureBuffer[5].X:= TextureBuffer[3].X + nWaves;
  1878 TextureBuffer[5].X:= TextureBuffer[3].X + nWaves;
  1812 TextureBuffer[5].Y:= 0;
  1879 TextureBuffer[5].Y:= frame * realHeight;
  1813 TextureBuffer[4].X:= TextureBuffer[5].X;
  1880 TextureBuffer[4].X:= TextureBuffer[5].X;
  1814 TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry;
  1881 TextureBuffer[4].Y:= (frame+1) * realHeight;
  1815 TextureBuffer[2].X:= TextureBuffer[3].X;
  1882 TextureBuffer[2].X:= TextureBuffer[3].X;
  1816 TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
  1883 TextureBuffer[2].Y:= (frame+1) * realHeight;
  1817 
  1884 
  1818 if (WorldEdge = weSea) then
  1885 if (WorldEdge = weSea) then
  1819     begin
  1886     begin
  1820     nWaves:= (topy - ViewTopY) / spriteWidth;
  1887     nWaves:= (topy - ViewTopY) / spriteWidth;
  1821 
  1888 
  1822     // left side
  1889     // left side
  1823     TextureBuffer[1].X:= TextureBuffer[3].X - nWaves;
  1890     TextureBuffer[1].X:= TextureBuffer[3].X - nWaves;
  1824     TextureBuffer[1].Y:= 0;
  1891     TextureBuffer[1].Y:= frame * realHeight;
  1825     TextureBuffer[0].X:= TextureBuffer[1].X;
  1892     TextureBuffer[0].X:= TextureBuffer[1].X;
  1826     TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry;
  1893     TextureBuffer[0].Y:= (frame+1) * realHeight;
  1827 
  1894 
  1828     // right side
  1895     // right side
  1829     TextureBuffer[7].X:= TextureBuffer[5].X + nWaves;
  1896     TextureBuffer[7].X:= TextureBuffer[5].X + nWaves;
  1830     TextureBuffer[7].Y:= 0;
  1897     TextureBuffer[7].Y:= frame * realHeight;
  1831     TextureBuffer[6].X:= TextureBuffer[7].X;
  1898     TextureBuffer[6].X:= TextureBuffer[7].X;
  1832     TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry;
  1899     TextureBuffer[6].Y:= (frame+1) * realHeight;
  1833     end;
  1900     end;
  1834 
  1901 
  1835 glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
  1902 glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
  1836 
  1903 
  1837 SetVertexPointer(@VertexBuffer[0], 8);
  1904 SetVertexPointer(@VertexBuffer[0], 8);