Merge remote-tracking branch 'glBitmap@DGL/master'
[LazOpenGLCore.git] / ugluMatrix.pas
1 unit ugluMatrix;
2
3 { Package:      OpenGLCore
4   Prefix:       glu - OpenGL Utils
5   Beschreibung: diese Unit enthält Matrix-Typen und Methoden um diese zu erstellen und zu manipulieren }
6
7 {$mode objfpc}{$H+}
8
9 interface
10
11 uses
12   Classes, SysUtils, ugluVector;
13
14 type
15   //Matrixtypen
16   TgluMatrix2ub = array[0..1] of TgluVector2ub;
17   TgluMatrix2i  = array[0..1] of TgluVector2i;
18   TgluMatrix2f  = array[0..1] of TgluVector2f;
19   TgluMatrix2d  = array[0..1] of TgluVector2d;
20
21   TgluMatrix3ub = array[0..2] of TgluVector3ub;
22   TgluMatrix3i  = array[0..2] of TgluVector3i;
23   TgluMatrix3f  = array[0..2] of TgluVector3f;
24   TgluMatrix3d  = array[0..2] of TgluVector3d;
25
26   TgluMatrix4ub = array[0..3] of TgluVector4ub;
27   TgluMatrix4i  = array[0..3] of TgluVector4i;
28   TgluMatrix4f  = array[0..3] of TgluVector4f;
29   TgluMatrix4d  = array[0..3] of TgluVector4d;
30
31   //MatrixPointer
32   PgluMatrix2ub = ^TgluMatrix2ub;
33   PgluMatrix2i  = ^TgluMatrix2i;
34   PgluMatrix2f  = ^TgluMatrix2f;
35   PgluMatrix2d  = ^TgluMatrix2d;
36
37   PgluMatrix3ub = ^TgluMatrix3ub;
38   PgluMatrix3i  = ^TgluMatrix3i;
39   PgluMatrix3f  = ^TgluMatrix3f;
40   PgluMatrix3d  = ^TgluMatrix3d;
41
42   PgluMatrix4ub = ^TgluMatrix4ub;
43   PgluMatrix4i  = ^TgluMatrix4i;
44   PgluMatrix4f  = ^TgluMatrix4f;
45   PgluMatrix4d  = ^TgluMatrix4d;
46
47   //Konstructoren
48   function gluMatrix4d(const m: TgluMatrix4f): TgluMatrix4d;
49
50   //Matrixfunktionen
51   function gluMatrixTranslate(const v: TgluVector3f): TgluMatrix4f;
52   function gluMatrixScale(const v: TgluVector3f): TgluMatrix4f; overload;
53   function gluMatrixScale(const s: Single): TgluMatrix4f; overload;
54   function gluMatrixRotate(axis: TgluVector3f; const angle: Single): TgluMatrix4f;
55   function gluMatrixMult(const m1, m2: TgluMatrix4f): TgluMatrix4f;
56   function gluMatrixMultVec(const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f;
57   function gluMatrixTranspose(const m: TgluMatrix3f): TgluMatrix3f; overload;
58   function gluMatrixTranspose(const m: TgluMatrix4f): TgluMatrix4f; overload;
59   function gluMatrixSubMatrix(const m:TgluMatrix4f; const s, z: Integer): TgluMatrix3f;
60   function gluMatrixDeterminant(const m: TgluMatrix3f): Single; overload;
61   function gluMatrixDeterminant(const m: TgluMatrix4f): Single; overload;
62   function gluMatrixAdjoint(const m: TgluMatrix4f): TgluMatrix4f;
63   function gluMatrixInvert(const m: TgluMatrix4f): TgluMatrix4f;
64
65   operator * (const m1, m2: TgluMatrix4f): TgluMatrix4f;
66   operator * (const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f;
67   operator * (const m: TgluMatrix4f; const v: TgluVector3f): TgluVector3f;
68
69 const
70   maAxisX = 0;
71   maAxisY = 1;
72   maAxisZ = 2;
73   maPos   = 3;
74   gluMatrixIdentity: TgluMatrix4f = ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1));
75
76 implementation
77
78 uses
79   Math;
80
81 operator * (const m1, m2: TgluMatrix4f): TgluMatrix4f;
82 begin
83   result := gluMatrixMult(m1, m2);
84 end;
85
86 operator * (const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f;
87 begin
88   result := gluMatrixMultVec(m, v);
89 end;
90
91 operator * (const m: TgluMatrix4f; const v: TgluVector3f): TgluVector3f;
92 begin
93   result := gluVector3f(gluMatrixMultVec(m, gluVEctor4f(v, 1.0)));
94 end;
95
96 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 function gluMatrix4d(const m: TgluMatrix4f): TgluMatrix4d;
98 var
99   i, j: Integer;
100 begin
101   for i := 0 to 3 do
102     for j := 0 to 3 do
103       result[i, j] := m[i, j];
104 end;
105
106 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107 //erstellt eine Translationsmatrix
108 //@v: Vektor der Translationsmatrix;
109 function gluMatrixTranslate(const v: TgluVector3f): TgluMatrix4f;
110 var
111   i: Integer;
112 begin
113   result := gluMatrixIdentity;
114   for i := 0 to 2 do
115     result[3, i] := v[i];
116 end;
117
118 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119 //erstellt eine Skalierungsmatrix
120 //@v: Vektor der Skalierungsmatrix;
121 function gluMatrixScale(const v: TgluVector3f): TgluMatrix4f;
122 var
123   i: Integer;
124 begin
125   result := gluMatrixIdentity;
126   for i := 0 to 2 do
127     result[i, i] := v[i];
128 end;
129
130 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 function gluMatrixScale(const s: Single): TgluMatrix4f;
132 var
133   i: Integer;
134 begin
135   result := gluMatrixIdentity;
136   for i := 0 to 2 do
137     result[i, i] := s;
138 end;
139
140 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
141 //erstellt eine Rotationsmatrix;
142 //@axis: Achse um die gedreht werden soll;
143 //@angle: Winkel mit dem gedreht werden soll;
144 function gluMatrixRotate(axis: TgluVector3f; const angle: Single): TgluMatrix4f;
145 var
146   X, Y, Z, a, s, c: Single;
147 begin
148   axis := gluVectorNormalize(axis);
149   X := axis[0];
150   Y := axis[1];
151   Z := axis[2];
152   a := angle/180*Pi;
153   s := sin(a);
154   c := cos(a);
155   result := gluMatrixIdentity;
156   result[maAxisX] := gluVector4f(
157     SQR(X) + (1-SQR(X))*c,
158     X*Y*(1-c) + Z*s,
159     X*Z*(1-c) - Y*s,
160     0);
161   result[maAxisY] := gluVector4f(
162     X*Y*(1-c) - Z*s,
163     SQR(Y) + (1-SQR(Y))*c,
164     Y*Z*(1-c) + X*s,
165     0);
166   result[maAxisZ] := gluVector4f(
167     X*Z*(1-c) + Y*s,
168     Y*Z*(1-c) - X*s,
169     SQR(Z) + (1-SQR(Z))*c,
170     0);
171 end;
172
173 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
174 //Mutlipliziert Matrix1 mit Matrix2
175 //@Matrix1: 1. Multiplikator;
176 //@Matrix2: 2. Multiplikator;
177 //@result: Matrix1 * Matrix2
178 function gluMatrixMult(const m1, m2: TgluMatrix4f): TgluMatrix4f;
179 var
180   x, y, i: Integer;
181   sum: Single;
182 begin
183   for x := 0 to 3 do begin
184     for y := 0 to 3 do begin
185       sum := 0;
186       for i := 0 to 3 do
187         sum := sum + m1[i, y] * m2[x, i];
188       result[x, y] := sum;
189     end;
190   end;
191 end;
192
193 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
194 //Multiplizerit eine Matrix mit einem Vektor
195 //@m: Matrix mit der multipliziert werden soll;
196 //@v: Vektor mit dem multipliziert werden soll;
197 //@result: Ergebnis der Multiplikation
198 function gluMatrixMultVec(const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f;
199 var
200   i, j: Integer;
201   sum: Single;
202 begin
203   for i := 0 to 3 do begin
204     sum := 0;
205     for j := 0 to 3 do
206       sum := sum + m[j,i] * v[j];
207     result[i] := sum;
208   end;
209 end;
210
211 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
212 //berechnet die Transponierte Matrix
213 //@m: Matrix die Transponiert werden soll;
214 //@result: Transponierte Matrix;
215 function gluMatrixTranspose(const m: TgluMatrix3f): TgluMatrix3f;
216 var
217   i, j: Integer;
218 begin
219   for i := 0 to 2 do
220     for j := 0 to 2 do
221       result[i, j] := m[j, i];
222 end;
223
224 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
225 //berechnet die Transponierte Matrix
226 //@m: Matrix die Transponiert werden soll;
227 //@result: Transponierte Matrix;
228 function gluMatrixTranspose(const m: TgluMatrix4f): TgluMatrix4f;
229 var
230   i, j: Integer;
231 begin
232   for i := 0 to 3 do
233     for j := 0 to 3 do
234       result[i, j] := m[j, i];
235 end;
236
237 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
238 //ermittelt die Untermatrix einer Matrix
239 //@m: Matrix derren Untermatrix berechnet werden soll;
240 //@s: Spalte die gelöscht werden soll;
241 //@z: Zeile die gelöscht werden soll;
242 //@result: Untermatrix von m
243 function gluMatrixSubMatrix(const m: TgluMatrix4f; const s, z: Integer): TgluMatrix3f;
244 var
245   x, y, i, j: Integer;
246 begin
247   for i := 0 to 2 do
248     for j := 0 to 2 do begin
249       x := i;
250       y := j;
251       if (i >= s) then
252         inc(x);
253       if (j >= z) then
254         inc(y);
255       result[i, j] := m[x, y];
256     end;
257 end;
258
259 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
260 //berechnet die Determinante einer Matrix
261 //@m: Matrix derren Determinaten berechnet werden soll;
262 //@result: Determinante von m
263 function gluMatrixDeterminant(const m: TgluMatrix3f): Single;
264 begin
265   result :=
266     m[0,0] * m[1,1] * m[2,2] +
267     m[1,0] * m[2,1] * m[0,2] +
268     m[2,0] * m[0,1] * m[1,2] -
269     m[2,0] * m[1,1] * m[0,2] -
270     m[1,0] * m[0,1] * m[2,2] -
271     m[0,0] * m[2,1] * m[1,2];
272 end;
273
274 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
275 //berechnet die Determinante einer Matrix
276 //@m: Matrix derren Determinaten berechnet werden soll;
277 //@result: Determinante von m
278 function gluMatrixDeterminant(const m: TgluMatrix4f): Single;
279 var
280   i: Integer;
281 begin
282   result := 0;
283   for i := 0 to 3 do
284     result := result + power(-1, i) * m[i, 0] * gluMatrixDeterminant(gluMatrixSubMatrix(m, i, 0));
285 end;
286
287 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
288 //berechnet die Adjunkte einer Matrix
289 //@m: Matrix derren Adjunkte berechnet werden soll;
290 //@result: Adjunkte von m
291 function gluMatrixAdjoint(const m: TgluMatrix4f): TgluMatrix4f;
292 var
293   i, j: Integer;
294 begin
295   for i := 0 to 3 do
296     for j := 0 to 3 do
297       result[i, j] := power(-1, i+j) * gluMatrixDeterminant(gluMatrixSubMatrix(m, i, j));
298   result := gluMatrixTranspose(result);
299 end;
300
301 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
302 //berechnet die inverse Matrix einer Matrix
303 //@m: Matrix derren Inverse berechnet werden soll;
304 //@result: Inverse Matrix von m;
305 function gluMatrixInvert(const m: TgluMatrix4f): TgluMatrix4f;
306 var
307   d: Single;
308   i, j: Integer;
309 begin
310   d := gluMatrixDeterminant(m);
311   result := gluMatrixAdjoint(m);
312   for i := 0 to 3 do
313     for j := 0 to 3 do
314       result[i,j] := result[i,j] / d;
315 end;
316
317 end.
318