Replaced matrix related FFP code with explicit matrix calculations.
authorWolfgang Steffens <WolfgangSteff@gmail.com>
Tue, 22 May 2012 09:25:03 +0200
changeset 7111 5ba5a92d74fb
parent 7108 eaef11c0d039
child 7125 bfb759d07288
Replaced matrix related FFP code with explicit matrix calculations. The modelview matrices now get uploaded at a single point via glLoadMatrix4 rather than using the GL1 matrix stack. In the GL2 variant this will become a uniform upload.
hedgewars/hwengine.pas
hedgewars/uGearsRender.pas
hedgewars/uRender.pas
hedgewars/uTypes.pas
--- a/hedgewars/hwengine.pas	Tue May 22 09:18:46 2012 +0200
+++ b/hedgewars/hwengine.pas	Tue May 22 09:25:03 2012 +0200
@@ -31,7 +31,7 @@
 
 uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler, uSound,
      uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions,
-     SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
+     SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uRender, uDebug, uCommandHandlers, uLandPainted
      {$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF};
 
 {$IFDEF HWLIBRARY}
@@ -419,6 +419,7 @@
         uVisualGears.initModule;
         uWorld.initModule;
         uCaptions.initModule;
+        uRender.initModule;
     end;
 end;
 
--- a/hedgewars/uGearsRender.pas	Tue May 22 09:18:46 2012 +0200
+++ b/hedgewars/uGearsRender.pas	Tue May 22 09:25:03 2012 +0200
@@ -54,9 +54,9 @@
     glDisable(GL_TEXTURE_2D);
     //glEnable(GL_LINE_SMOOTH);
 
-    glPushMatrix;
-
-    glTranslatef(WorldDx, WorldDy, 0);
+    ResetRotation;
+    SetOffset(WorldDx, WorldDy);
+    UpdateModelview;
 
     glLineWidth(4.0);
 
@@ -66,8 +66,6 @@
     glDrawArrays(GL_LINE_STRIP, 0, RopePoints.Count + 2);
     Tint($FF, $FF, $FF, $FF);
 
-    glPopMatrix;
-
     glEnable(GL_TEXTURE_2D);
     //glDisable(GL_LINE_SMOOTH)
     end
--- a/hedgewars/uRender.pas	Tue May 22 09:18:46 2012 +0200
+++ b/hedgewars/uRender.pas	Tue May 22 09:25:03 2012 +0200
@@ -22,7 +22,9 @@
 
 interface
 
-uses SDLh, uTypes, GLunit, uConsts, uTextures;
+uses SDLh, uTypes, GLunit, uConsts, uTextures, math;
+
+procedure initModule;
 
 procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
@@ -51,11 +53,85 @@
 procedure Tint                  (r, g, b, a: Byte); inline;
 procedure Tint                  (c: Longword); inline;
 
+// This is just temporary and becomes non public once everything changed to GL2
+procedure UpdateModelview;
+procedure ResetModelview;
+procedure SetOffset(X, Y: Longint);
+procedure ResetRotation;
+
 
 implementation
 uses uVariables;
 
 var LastTint: LongWord = 0;
+    Modelview: TMatrix4x4f;
+
+const DegToRad =  0.01745329252; // 2PI / 360
+
+procedure UpdateModelview;
+begin
+glLoadMatrixf(@Modelview[0,0]);
+end;
+
+procedure ResetModelview;
+begin
+Modelview[0,0]:= 1.0; Modelview[1,0]:=0.0; Modelview[3,0]:= 0;
+Modelview[0,1]:= 0.0; Modelview[1,1]:=1.0; Modelview[3,1]:= 0;
+UpdateModelview;
+end;
+
+procedure SetOffset(X, Y: Longint);
+begin
+Modelview[3,0]:= X;
+Modelview[3,1]:= Y;
+end;
+
+procedure AddOffset(X, Y: GLfloat); // probably want to refactor this to use integers
+begin
+Modelview[3,0]:=Modelview[3,0] + Modelview[0,0]*X + Modelview[1,0]*Y;
+Modelview[3,1]:=Modelview[3,1] + Modelview[0,1]*X + Modelview[1,1]*Y;
+end;
+
+procedure SetScale(Scale: GLfloat);
+begin
+Modelview[0,0]:= Scale;
+Modelview[1,1]:= Scale;
+end;
+
+procedure AddScale(Scale: GLfloat);
+begin
+Modelview[0,0]:= Modelview[0,0]*Scale; Modelview[1,0]:= Modelview[1,0]*Scale;
+Modelview[0,1]:= Modelview[0,1]*Scale; Modelview[1,1]:= Modelview[1,1]*Scale;
+end;
+
+procedure AddScale(X, Y: GLfloat);
+begin
+Modelview[0,0]:= Modelview[0,0]*X; Modelview[1,0]:= Modelview[1,0]*Y;
+Modelview[0,1]:= Modelview[0,1]*X; Modelview[1,1]:= Modelview[1,1]*Y;
+end;
+
+
+procedure SetRotation(Angle, ZAxis: GLfloat);
+var s, c: Extended;
+begin
+SinCos(Angle*DegToRad, s, c);
+Modelview[0,0]:= c;       Modelview[1,0]:=-s*ZAxis;
+Modelview[0,1]:= s*ZAxis; Modelview[1,1]:= c;
+end;
+
+procedure ResetRotation;
+begin
+Modelview[0,0]:= 1.0; Modelview[1,0]:=0.0;
+Modelview[0,1]:= 0.0; Modelview[1,1]:=1.0;
+end;
+
+procedure LoadIdentity(out Matrix: TMatrix4x4f);
+begin
+Matrix[0,0]:= 1.0; Matrix[1,0]:=0.0; Matrix[2,0]:=0.0; Matrix[3,0]:=0.0;
+Matrix[0,1]:= 0.0; Matrix[1,1]:=1.0; Matrix[2,1]:=0.0; Matrix[3,1]:=0.0;
+Matrix[0,2]:= 0.0; Matrix[1,2]:=0.0; Matrix[2,2]:=1.0; Matrix[3,2]:=0.0;
+Matrix[0,3]:= 0.0; Matrix[1,3]:=0.0; Matrix[2,3]:=0.0; Matrix[3,3]:=1.0;
+end;
 
 procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
 begin
@@ -112,18 +188,17 @@
 
 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
 begin
-
-glPushMatrix;
-glTranslatef(X, Y, 0);
-glScalef(Scale, Scale, 1);
+SetOffset(X, Y);
+ResetRotation;
+SetScale(Scale);
+UpdateModelview;
 
 glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
 
 glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb);
 glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
-
-glPopMatrix
+ResetModelview;
 end;
 
 procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
@@ -142,14 +217,13 @@
 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
     exit;
 
-glPushMatrix;
-glTranslatef(X, Y, 0);
+SetOffset(X, Y);
 if Dir = 0 then Dir:= 1;
 
-glRotatef(Angle, 0, 0, Dir);
-
-glTranslatef(Dir*OffsetX, OffsetY, 0);
-glScalef(Scale, Scale, 1);
+SetRotation(Angle, Dir);
+AddOffset(Dir*OffsetX, OffsetY);
+AddScale(Scale);
+UpdateModelview;
 
 // Any reason for this call? And why only in t direction, not s?
 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -180,7 +254,7 @@
 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
-glPopMatrix
+ResetModelview;
 end;
 
 procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
@@ -193,19 +267,18 @@
 
 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
 begin
-glPushMatrix;
-glTranslatef(X, Y, 0);
-
+SetOffset(X, Y);
 if Dir < 0 then
-    glRotatef(Angle, 0, 0, -1)
+    SetRotation(Angle, -1.0)
 else
-    glRotatef(Angle, 0, 0,  1);
+    SetRotation(Angle, 1.0);
 if Dir < 0 then
-    glScalef(-1.0, 1.0, 1.0);
+    AddScale(-1.0, 1.0);
+UpdateModelview;
 
 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
 
-glPopMatrix
+ResetModelview;
 end;
 
 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
@@ -217,17 +290,16 @@
 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
     exit;
 
-glPushMatrix;
-glTranslatef(X, Y, 0);
+SetOffset(X, Y);
 
 if Dir < 0 then
     begin
     hw:= - hw;
-    glRotatef(Angle, 0, 0, -1);
+    SetRotation(Angle, -1.0);
     end
 else
-    glRotatef(Angle, 0, 0,  1);
-
+    SetRotation(Angle, 1.0);
+UpdateModelview;
 
 glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
 
@@ -244,7 +316,7 @@
 glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
-glPopMatrix
+ResetModelview;
 end;
 
 procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt);
@@ -308,8 +380,9 @@
     glDisable(GL_TEXTURE_2D);
     glEnable(GL_LINE_SMOOTH);
 
-    glPushMatrix;
-    glTranslatef(WorldDx, WorldDy, 0);
+    ResetRotation;
+    SetOffset(WorldDx, WorldDy);
+    UpdateModelview;
     glLineWidth(Width);
 
     Tint(r, g, b, a);
@@ -322,7 +395,7 @@
     glDrawArrays(GL_LINES, 0, Length(VertexBuffer));
     Tint($FF, $FF, $FF, $FF);
     
-    glPopMatrix;
+    ResetModelview;
     
     glEnable(GL_TEXTURE_2D);
     glDisable(GL_LINE_SMOOTH);
@@ -331,6 +404,10 @@
 procedure DrawFillRect(r: TSDL_Rect);
 var VertexBuffer: array [0..3] of TVertex2f;
 begin
+SetOffset(0, 0);
+ResetRotation;
+UpdateModelview;
+
 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
 if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
     exit;
@@ -354,7 +431,9 @@
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
 Tint($FF, $FF, $FF, $FF);
-glEnable(GL_TEXTURE_2D)
+glEnable(GL_TEXTURE_2D);
+
+ResetModelview;
 end;
 
 procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte); 
@@ -375,13 +454,15 @@
     end;
     glDisable(GL_TEXTURE_2D);
     glEnable(GL_LINE_SMOOTH);
-    glPushMatrix;
+    SetOffset(0, 0);
+    ResetRotation;
+    UpdateModelview;
     glLineWidth(Width);
     glVertexPointer(2, GL_FLOAT, 0, @CircleVertex[0]);
     glDrawArrays(GL_LINE_LOOP, 0, 60);
-    glPopMatrix;
     glEnable(GL_TEXTURE_2D);
     glDisable(GL_LINE_SMOOTH);
+    ResetModelview;
 end;
 
 
@@ -410,9 +491,9 @@
     r.h:=32;
     ComputeTexcoords(HHTexture, @r, @TextureBuffer);
 
-    glPushMatrix();
-    glTranslatef(X, Y, 0);
-    glRotatef(Angle, 0, 0, 1);
+    SetOffset(X, Y);
+    SetRotation(Angle, 1.0);
+    UpdateModelview;
 
     glBindTexture(GL_TEXTURE_2D, HHTexture^.atlas^.id);
     if Dir = -1 then
@@ -422,7 +503,7 @@
     glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-    glPopMatrix
+    ResetModelview;
 end;
 
 procedure DrawScreenWidget(widget: POnScreenWidget);
@@ -499,4 +580,9 @@
     Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
 end;
 
+procedure initModule;
+begin
+LoadIdentity(Modelview);
+end;
+
 end.
--- a/hedgewars/uTypes.pas	Tue May 22 09:18:46 2012 +0200
+++ b/hedgewars/uTypes.pas	Tue May 22 09:25:03 2012 +0200
@@ -199,6 +199,8 @@
             X, Y: GLint;
             end;
 
+    TMatrix4x4f = array[0..3, 0..3] of GLfloat;
+
     PAtlas = ^TAtlas;
     PTexture = ^TTexture;