You can see the whole 3D unit here, didn't paste the 2D math but you can figure if needed functions out i suppose, or ask:
http://pastebin.com/gtLhUvj5

[pascal]// Create a rotation matrix
function CreateMatrix(const x, y, z: TVector): TMatrix;
begin
result[0,0]:=x.x; result[0,1]:=x.y; result[0,2]:=x.z; result[0,3]:=0;
result[1,0]:=y.x; result[1,1]:=y.y; result[1,2]:=y.z; result[1,3]:=0;
result[2,0]:=z.x; result[2,1]:=z.y; result[2,2]:=z.z; result[2,3]:=0;
result[3,0]:=0; result[3,1]:=0; result[3,2]:=0; result[3,3]:=1;
end;

// Rotation matrix written with rows and columns switched
function CreateMatrix2(const x, y, z: TVector): TMatrix;
begin
result[0,0]:=x.x; result[1,0]:=x.y; result[2,0]:=x.z; result[3,0]:=0;
result[0,1]:=y.x; result[1,1]:=y.y; result[2,1]:=y.z; result[3,1]:=0;
result[0,2]:=z.x; result[1,2]:=z.y; result[2,2]:=z.z; result[3,2]:=0;
result[0,3]:=0; result[1,3]:=0; result[2,3]:=0; result[3,3]:=1;
end;

function CreateTranslateMatrix(const p: TVector): TMatrix;
begin
result:=NewMatrix;
result[3,0]:=p.x; result[3,1]:=p.y; result[3,2]:=p.z;
end;[/pascal]

Edit: I changed the code a bit to make everything click. LookAt function has to use CreateMatrix2 that uses opposite row direction while usual operations such as MatrixOnPlane() use CreateMatrix.