moved generic matrix code to uMatrix.pas
authorWolfgang Steffens <WolfgangSteff@gmail.com>
Mon, 28 May 2012 10:38:27 +0200
changeset 7138 f8248bcba8f1
parent 7136 6f3c9ec79338
child 7186 013deb83086b
moved generic matrix code to uMatrix.pas updated shader and client logic to use a mat4 rather than ftransform or gl_ModelViewProjectionMatrix.
hedgewars/hwengine.pas
hedgewars/uMatrix.pas
hedgewars/uRender.pas
hedgewars/uStore.pas
hedgewars/uVariables.pas
share/hedgewars/Data/Shaders/default.vs
--- a/hedgewars/hwengine.pas	Mon May 28 10:34:33 2012 +0200
+++ b/hedgewars/hwengine.pas	Mon May 28 10:38:27 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, uRender, uDebug, uCommandHandlers, uLandPainted
+     SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
      {$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF};
 
 {$IFDEF HWLIBRARY}
@@ -419,7 +419,6 @@
         uVisualGears.initModule;
         uWorld.initModule;
         uCaptions.initModule;
-        uRender.initModule;
     end;
 end;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uMatrix.pas	Mon May 28 10:38:27 2012 +0200
@@ -0,0 +1,123 @@
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit uMatrix;
+
+interface
+
+uses uTypes, gl;
+
+procedure MatrixLoadIdentity(out Result: TMatrix4x4f);
+procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f);
+
+implementation
+
+procedure MatrixLoadIdentity(out Result: TMatrix4x4f);
+begin
+    Result[0,0]:= 1.0; Result[1,0]:=0.0; Result[2,0]:=0.0; Result[3,0]:=0.0;
+    Result[0,1]:= 0.0; Result[1,1]:=1.0; Result[2,1]:=0.0; Result[3,1]:=0.0;
+    Result[0,2]:= 0.0; Result[1,2]:=0.0; Result[2,2]:=1.0; Result[3,2]:=0.0;
+    Result[0,3]:= 0.0; Result[1,3]:=0.0; Result[2,3]:=0.0; Result[3,3]:=1.0;
+end;
+
+procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f);
+var
+    test: TMatrix4x4f;
+    i, j: Integer;
+    error: boolean;
+begin
+    Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3];
+    Result[0,1]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3];
+    Result[0,2]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3];
+    Result[0,3]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3];
+
+    Result[1,0]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3];
+    Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3];
+    Result[1,2]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3];
+    Result[1,3]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3];
+
+    Result[2,0]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3];
+    Result[2,1]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3];
+    Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3];
+    Result[2,3]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3];
+
+    Result[3,0]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3];
+    Result[3,1]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3];
+    Result[3,2]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3];
+    Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3];
+
+{
+    Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3];
+    Result[0,1]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3];
+    Result[0,2]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3];
+    Result[0,3]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3];
+  
+    Result[1,0]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3];
+    Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3];
+    Result[1,2]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3];
+    Result[1,3]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3];
+
+    Result[2,0]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3];
+    Result[2,1]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3];
+    Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3];
+    Result[2,3]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3];
+
+    Result[3,0]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3];
+    Result[3,1]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3];
+    Result[3,2]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3];
+    Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3];
+}
+    glPushMatrix;
+    glLoadMatrixf(@lhs[0, 0]);
+    glMultMatrixf(@rhs[0, 0]);
+    glGetFloatv(GL_MODELVIEW_MATRIX, @test[0, 0]);
+    glPopMatrix;
+
+    error:=false;
+    for i:=0 to 3 do
+      for j:=0 to 3 do
+        if Abs(test[i, j] - Result[i, j]) > 0.000001 then
+          error:=true;
+
+    if error then
+    begin
+        writeln('shall:');
+        for i:=0 to 3 do
+        begin
+          for j:=0 to 3 do
+            write(test[i, j]);
+          writeln;
+        end;
+
+        writeln('is:');
+        for i:=0 to 3 do
+        begin
+          for j:=0 to 3 do
+            write(Result[i, j]);
+          writeln;
+        end;
+        halt(0);
+    end;
+
+
+end;
+
+
+end.
--- a/hedgewars/uRender.pas	Mon May 28 10:34:33 2012 +0200
+++ b/hedgewars/uRender.pas	Mon May 28 10:38:27 2012 +0200
@@ -24,8 +24,6 @@
 
 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);
 procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
@@ -61,76 +59,71 @@
 
 
 implementation
-uses uVariables;
+uses uVariables, uStore;
 
 var LastTint: LongWord = 0;
-    Modelview: TMatrix4x4f;
 
 const DegToRad =  0.01745329252; // 2PI / 360
 
 procedure UpdateModelview;
 begin
-glLoadMatrixf(@Modelview[0,0]);
+{$IFDEF GL2}
+    UpdateModelviewProjection;
+{$ELSE}
+    glLoadMatrixf(@mModelview[0,0]);
+{$ENDIF}
 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;
+    mModelview[0,0]:= 1.0; mModelview[1,0]:=0.0; mModelview[3,0]:= 0;
+    mModelview[0,1]:= 0.0; mModelview[1,1]:=1.0; mModelview[3,1]:= 0;
+    UpdateModelview;
 end;
 
 procedure SetOffset(X, Y: Longint);
 begin
-Modelview[3,0]:= X;
-Modelview[3,1]:= Y;
+    mModelview[3,0]:= X;
+    mModelview[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;
+    mModelview[3,0]:=mModelview[3,0] + mModelview[0,0]*X + mModelview[1,0]*Y;
+    mModelview[3,1]:=mModelview[3,1] + mModelview[0,1]*X + mModelview[1,1]*Y;
 end;
 
 procedure SetScale(Scale: GLfloat);
 begin
-Modelview[0,0]:= Scale;
-Modelview[1,1]:= Scale;
+    mModelview[0,0]:= Scale;
+    mModelview[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;
+    mModelview[0,0]:= mModelview[0,0]*Scale; mModelview[1,0]:= mModelview[1,0]*Scale;
+    mModelview[0,1]:= mModelview[0,1]*Scale; mModelview[1,1]:= mModelview[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;
+    mModelview[0,0]:= mModelview[0,0]*X; mModelview[1,0]:= mModelview[1,0]*Y;
+    mModelview[0,1]:= mModelview[0,1]*X; mModelview[1,1]:= mModelview[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;
+    SinCos(Angle*DegToRad, s, c);
+    mModelview[0,0]:= c;       mModelview[1,0]:=-s*ZAxis;
+    mModelview[0,1]:= s*ZAxis; mModelview[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;
+    mModelview[0,0]:= 1.0; mModelview[1,0]:=0.0;
+    mModelview[0,1]:= 0.0; mModelview[1,1]:=1.0;
 end;
 
 procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
@@ -580,9 +573,4 @@
     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/uStore.pas	Mon May 28 10:34:33 2012 +0200
+++ b/hedgewars/uStore.pas	Mon May 28 10:38:27 2012 +0200
@@ -45,9 +45,13 @@
 procedure SwapBuffers; inline;
 procedure UpdateProjection;
 
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+{$ENDIF}
+
 implementation
 uses uMisc, uConsole, uMobile, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands,
-     uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF};
+     uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}, uMatrix;
 
 //type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
 
@@ -60,6 +64,7 @@
 {$ENDIF}
 {$IFDEF GL2}
     Shader: GLuint;
+    uMVPLocation: GLint;
 {$ENDIF}
 
 function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
@@ -791,6 +796,8 @@
     Shader:= CompileProgram('default');
     glUseProgram(Shader);
     glUniform1i(glGetUniformLocation(Shader, 'tex'), 0);
+    uMVPLocation:= glGetUniformLocation(Shader, 'mvp');
+
 {$ENDIF}
 
 {$IFNDEF S3D_DISABLED}
@@ -855,18 +862,33 @@
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 end;
 
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+var
+    mvp: TMatrix4x4f;
+begin
+    MatrixMultiply(mvp, mProjection, mModelview);
+    glUniformMatrix4fv(uMVPLocation, 1, GL_FALSE, @mvp[0, 0]);
+end;
+{$ENDIF GL2}
+
 procedure UpdateProjection;
-var mat: array[0..15] of GLfloat;
+var
     s: GLfloat;
 begin
     s:=cScaleFactor;
+    mProjection[0,0]:= s/cScreenWidth; mProjection[0,1]:=  0.0;             mProjection[0,2]:=0.0; mProjection[0,3]:=  0.0;
+    mProjection[1,0]:= 0.0;            mProjection[1,1]:= -s/cScreenHeight; mProjection[1,2]:=0.0; mProjection[1,3]:=  0.0;
+    mProjection[2,0]:= 0.0;            mProjection[2,1]:=  0.0;             mProjection[2,2]:=1.0; mProjection[2,3]:=  0.0;
+    mProjection[3,0]:= cStereoDepth;   mProjection[3,1]:=  s/2;             mProjection[3,2]:=0.0; mProjection[3,3]:=  1.0;
+
+    {$IFDEF GL2}
+    UpdateModelviewProjection;
+    {$ELSE}
     glMatrixMode(GL_PROJECTION);
-    mat[ 0]:= s/cScreenWidth; mat[ 1]:=  0.0;             mat[ 2]:=0.0; mat[ 3]:=  0.0;
-    mat[ 4]:= 0.0;            mat[ 5]:= -s/cScreenHeight; mat[ 6]:=0.0; mat[ 7]:=  0.0;
-    mat[ 8]:= 0.0;            mat[ 9]:=  0.0;             mat[10]:=1.0; mat[11]:=  0.0;
-    mat[12]:= cStereoDepth;   mat[13]:=  s/2;             mat[14]:=0.0; mat[15]:=  1.0;
-    glLoadMatrixf(@mat);
+    glLoadMatrixf(@mProjection[0, 0]);
     glMatrixMode(GL_MODELVIEW);
+    {$ENDIF}    
 end;
 
 procedure SetScale(f: GLfloat);
--- a/hedgewars/uVariables.pas	Mon May 28 10:34:33 2012 +0200
+++ b/hedgewars/uVariables.pas	Mon May 28 10:38:27 2012 +0200
@@ -21,7 +21,7 @@
 unit uVariables;
 interface
 
-uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile;
+uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile, uMatrix;
 
 var
 /////// init flags ///////
@@ -2465,6 +2465,9 @@
 
     lastTurnChecksum : Longword;
 
+    mModelview: TMatrix4x4f;
+    mProjection: TMatrix4x4f;
+
 var trammo:  array[TAmmoStrId] of ansistring;   // name of the weapon
     trammoc: array[TAmmoStrId] of ansistring;   // caption of the weapon
     trammod: array[TAmmoStrId] of ansistring;   // description of the weapon
@@ -2614,6 +2617,9 @@
     GrayScale:= false;
 
     LuaGoals:= '';
+
+    MatrixLoadIdentity(mModelview);
+    MatrixLoadIdentity(mProjection);
 end;
 
 procedure freeModule;
--- a/share/hedgewars/Data/Shaders/default.vs	Mon May 28 10:34:33 2012 +0200
+++ b/share/hedgewars/Data/Shaders/default.vs	Mon May 28 10:38:27 2012 +0200
@@ -1,10 +1,11 @@
 // !!!just testing!!! 
 // This is not GLSL 1.3+ compatible, as its using the compatibility profile!
+uniform mat4 mvp;
 varying vec4 tint;
 
 void main()
 {
-    gl_Position = ftransform();
+    gl_Position = mvp * gl_Vertex;
     gl_TexCoord[0] = gl_MultiTexCoord0;
     tint = gl_Color;
 }