Main methods are:
- Matrix
- Prepares the matrix for a given vector
- Identity
- Fills the matrix with a diagonal of 1 (http://cnx.org/content/m18293/latest/)
- |1 0 0|
- |0 1 0|
- |0 0 1|
- Add
- Sum two matrices
- Multiply
- Multiply two matrices
- Subtract
- Subtracts two matrices
Implementation
unit BB.Math.Matrix;
interface
uses
BB.Types;
type
T4x4 = array[0..2, 0..3] of TFloat;
PMatrix = ^TMatrix;
TMatrix = record
public
_4x4: T4x4;
constructor Create(aX, aY, aZ: TFloat); overload;
//constructor Create(const aVector: TVector); overload;
class operator Multiply(const aMatrixA, aMatrixB: TMatrix): TMatrix; inline;
class operator Add(const aMatrixA, aMatrixB: TMatrix): TMatrix; inline;
class operator Subtract(const aMatrixA, aMatrixB: TMatrix): TMatrix; inline;
procedure Matrix(aX, aY, aZ: TFloat);
procedure Identity;
procedure Clear;
procedure Transpose(const aMatrix: TMatrix);
end;
implementation
uses
BB.Math;
{ TMatrix }
class operator TMatrix.Add(const aMatrixA, aMatrixB: TMatrix): TMatrix;
var
i, j: integer;
begin
for j := High(T4x4) DownTo Low(T4x4) do
for i := High(T4x4) DownTo Low(T4x4) do
Result._4x4[j, i] := aMatrixA._4x4[i, j] + aMatrixB._4x4[i, j];
end;
constructor TMatrix.Create(aX, aY, aZ: TFloat);
begin
Matrix(aX, aY, aZ);
end;
procedure TMatrix.Identity;
var
i, j: integer;
begin
j := High(T4x4);
while j >= Low(T4x4) do
begin
i := High(T4x4);
while i >= Low(T4x4) do
begin
_4x4[j, i] := Ord(i = j);
Dec(i);
end;
Dec(j);
end;
end;
procedure TMatrix.Matrix(aX, aY, aZ: TFloat);
var
xSin, xCos, ySin, yCos, zSin, zCos, sxsz, sxcz, szcx, cxcz: TFloat;
begin
SinCos(aX * RAD, xSin, xCos);
SinCos(aY * RAD, ySin, yCos);
SinCos(aZ * RAD, zSin, zCos);
sxsz := xSin * zSin;
sxcz := xSin * zCos;
szcx := zSin * xCos;
cxcz := xCos * zCos;
_4x4[0, 0] := yCos * zCos;
_4x4[1, 0] := yCos * zSin;
_4x4[2, 0] := -ySin;
_4x4[0, 1] := ySin * sxcz - szcx;
_4x4[1, 1] := ySin * sxsz + cxcz;
_4x4[2, 1] := xSin * yCos;
_4x4[0, 2] := ySin * cxcz + sxsz;
_4x4[1, 2] := ySin * szcx - sxcz;
_4x4[2, 2] := xCos * yCos;
end;
class operator TMatrix.Multiply(const aMatrixA, aMatrixB: TMatrix): TMatrix;
var
i, j: integer;
begin
j := High(T4x4);
while j >= Low(T4x4) do
begin
i := High(T4x4);
while i >= Low(T4x4) do
begin
Result._4x4[i, j] := (aMatrixA._4x4[i, 0] * aMatrixB._4x4[0, j]) +
(aMatrixA._4x4[i, 1] * aMatrixB._4x4[1, j]) +
(aMatrixA._4x4[i, 2] * aMatrixB._4x4[2, j])
{ + (m1[i, 3] * m2[3, j])};
Dec(i);
end;
Dec(j);
end;
end;
procedure TMatrix.Clear;
begin
FillChar(_4x4, SizeOf(_4x4), 0);
end;
class operator TMatrix.Subtract(const aMatrixA, aMatrixB: TMatrix): TMatrix;
var
i, j: integer;
begin
for j := High(T4x4) DownTo Low(T4x4) do
for i := High(T4x4) DownTo Low(T4x4) do
Result._4x4[j, i] := aMatrixA._4x4[i, j] - aMatrixB._4x4[i, j];
end;
procedure TMatrix.Transpose(const aMatrix: TMatrix);
var
i, j: integer;
begin
for j := High(T4x4) downto Low(T4x4) do
for i := High(T4x4) downto Low(T4x4) do
_4x4[j, i] := aMatrix._4x4[i, j];
end;
end.
The way that a sprite (surface) ir rotated is via vectors and matrices:
var
matrix: TMatrix;
vector: TVector;
w, h,
x, y: integer;
poly: TPolygon;
begin
matrix := TMatrix.Create(0, 0, -aAngle);
w := GetWidth(Zoom) div 2;
h := GetHeight(Zoom) div 2;
x := FX;
y := FY;
//1
//xxx
//3xxx2
vector.Rotate(TVector.Create(-w, -h, 0), matrix);
poly[0] := TVector.Create(x + vector.X, y + vector.Y, FZ);
vector.Rotate(TVector.Create(w, h, 0), matrix);
poly[1] := TVector.Create(x + vector.X, y + vector.Y, FZ);
vector.Rotate(TVector.Create(-w, h, 0), matrix);
poly[2] := TVector.Create(x + vector.X, y + vector.Y, FZ);
DrawPoly(poly);
//1xxx2
// xxx
// 3
vector.Rotate(TVector.Create(-w, -h, 0), matrix);
poly[0] := TVector.Create(x + vector.X, y + vector.Y, FZ);
vector.Rotate(TVector.Create(w, -h, 0), matrix);
poly[1] := TVector.Create(x + vector.X, y + vector.Y, FZ);
vector.Rotate(TVector.Create(w, h, 0), matrix);
poly[2] := TVector.Create(x + vector.X, y + vector.Y, FZ);
DrawPoly(poly);
//In this case what is filled is a polygon,
//so with the rotation of the two triangles we get a rectangle,
//after apply a texture on that rectangle we get our sprite zoomed and/or
//rotated
end;
No comments:
Post a Comment