Source file : globe_3d-math.adb
with GL.Math;
package body GLOBE_3D.Math is
use GL, GL.Math, REF;
--------------
-- Matrices --
--------------
function "*"(A,B: Matrix_33) return Matrix_33 is
r: Real; AB: Matrix_33;
begin
for i in 1..3 loop
for j in 1..3 loop
r:= 0.0;
for k in 1..3 loop
r:= r + (A(i,k) * B(k,j));
end loop;
AB(i,j):= r;
end loop;
end loop;
return AB;
end "*";
function "*"(A: Matrix_33; x: Vector_3D) return Vector_3D is
r: Real;
Ax: Vector_3D;
-- banana skin: Matrix has range 1..3, Vector 0..2 (GL)
begin
for i in 1..3 loop
r:= 0.0;
for j in 1..3 loop
r:= r + A(i,j) * x(j-1);
end loop;
Ax(i-1):= r;
end loop;
return Ax;
end "*";
function "*"(A: Matrix_44; x: Vector_3D) return Vector_3D is
r: Real;
type Vector_4D is array (0..3) of GL.Double;
x_4D : constant Vector_4D := (x(0), x(1), x(2) , 1.0);
Ax : Vector_4D;
-- banana skin: Matrix has range 1..3, Vector 0..2 (GL)
begin
for i in 1..4 loop
r:= 0.0;
for j in 1..4 loop
r:= r + A(i,j) * x_4D(j-1);
end loop;
Ax(i-1):= r;
end loop;
return (Ax (0), Ax (1), Ax(2));
end "*";
function "*"(A: Matrix_44; x: Vector_3D) return Vector_4D is
r: Real;
x_4D : constant Vector_4D := (x(0), x(1), x(2) , 1.0);
Ax : Vector_4D;
-- banana skin: Matrix has range 1..3, Vector 0..2 (GL)
begin
for i in 1..4 loop
r:= 0.0;
for j in 1..4 loop
r:= r + A(i,j) * x_4D(j-1);
end loop;
Ax(i-1):= r;
end loop;
return Ax;
end "*";
function Transpose(A: Matrix_33) return Matrix_33 is
begin
return ( (A(1,1),A(2,1),A(3,1)),
(A(1,2),A(2,2),A(3,2)),
(A(1,3),A(2,3),A(3,3)));
end Transpose;
function Transpose(A: Matrix_44) return Matrix_44 is
begin
return ( (A(1,1),A(2,1),A(3,1),A(4,1)),
(A(1,2),A(2,2),A(3,2),A(4,2)),
(A(1,3),A(2,3),A(3,3),A(4,3)),
(A(1,4),A(2,4),A(3,4),A(4,4)));
end Transpose;
function Det(A: Matrix_33) return Real is
begin
return
A(1,1) * A(2,2) * A(3,3) +
A(2,1) * A(3,2) * A(1,3) +
A(3,1) * A(1,2) * A(2,3) -
A(3,1) * A(2,2) * A(1,3) -
A(2,1) * A(1,2) * A(3,3) -
A(1,1) * A(3,2) * A(2,3);
end Det;
function XYZ_rotation(ax,ay,az: Real) return Matrix_33 is
Mx, My, Mz: Matrix_33; c,s: Real;
begin
-- Around X
c:= Cos( ax );
s:= Sin( ax );
Mx:= ( (1.0,0.0,0.0),
(0.0, c, -s),
(0.0, s, c) );
-- Around Y
c:= Cos( ay );
s:= Sin( ay );
My:= ( ( c,0.0, -s),
(0.0,1.0,0.0),
( s,0.0, c) );
-- Around Z
c:= Cos( az );
s:= Sin( az );
Mz:= ( ( c, -s,0.0),
( s, c,0.0),
(0.0,0.0,1.0) );
return Mz * My * Mx;
end XYZ_rotation;
function XYZ_rotation(v: Vector_3D) return Matrix_33 is
begin
return XYZ_rotation(v(0),v(1),v(2));
end XYZ_rotation;
function Look_at(direction: Vector_3D) return Matrix_33 is
v1, v2, v3: Vector_3D;
begin
-- GL's look direction is the 3rd dimension (z)
v3:= Normalized(direction);
v2:= Normalized((v3(2),0.0,-v3(0)));
v1:= v2 * v3;
return
(((v1(0),v2(0),v3(0)),
(v1(1),v2(1),v3(1)),
(v1(2),v2(2),v3(2))
));
end Look_at;
function sub_Matrix (Self : in Matrix; start_Row, end_Row : in Positive;
start_Col, end_Col : in Positive) return Matrix
is
the_sub_Matrix : Matrix (1 .. end_Row - start_Row + 1,
1 .. end_Col - start_Col + 1);
begin
for Row in the_sub_Matrix'Range (1) loop
for Col in the_sub_Matrix'Range (2) loop
the_sub_Matrix (Row, Col) := Self (Row + start_Row - 1,
Col + start_Col - 1);
end loop;
end loop;
return the_sub_Matrix;
end sub_Matrix;
function Look_at (eye, center, up : Vector_3D) return Matrix_33
is
forward : constant Vector_3D := Normalized ((center (0) - eye (0), center (1) - eye (1), center (2) - eye (2)));
side : constant Vector_3D := Normalized (forward * up);
new_up : constant Vector_3D := side * forward;
begin
return (( side (0), side (1), side (2)),
( new_up (0), new_up (1), new_up (2)),
(-forward (0), -forward (1), -forward (2)));
end Look_at;
-- Following procedure is from Project Spandex, by Paul Nettle
procedure Re_Orthonormalize(M: in out Matrix_33) is
dot1,dot2,vlen: Real;
begin
dot1:= M(1,1) * M(2,1) + M(1,2) * M(2,2) + M(1,3) * M(2,3);
dot2:= M(1,1) * M(3,1) + M(1,2) * M(3,2) + M(1,3) * M(3,3);
M(1,1) := M(1,1) - dot1 * M(2,1) - dot2 * M(3,1);
M(1,2) := M(1,2) - dot1 * M(2,2) - dot2 * M(3,2);
M(1,3) := M(1,3) - dot1 * M(2,3) - dot2 * M(3,3);
vlen:= 1.0 / Sqrt(M(1,1) * M(1,1) +
M(1,2) * M(1,2) +
M(1,3) * M(1,3));
M(1,1):= M(1,1) * vlen;
M(1,2):= M(1,2) * vlen;
M(1,3):= M(1,3) * vlen;
dot1:= M(2,1) * M(1,1) + M(2,2) * M(1,2) + M(2,3) * M(1,3);
dot2:= M(2,1) * M(3,1) + M(2,2) * M(3,2) + M(2,3) * M(3,3);
M(2,1) := M(2,1) - dot1 * M(1,1) - dot2 * M(3,1);
M(2,2) := M(2,2) - dot1 * M(1,2) - dot2 * M(3,2);
M(2,3) := M(2,3) - dot1 * M(1,3) - dot2 * M(3,3);
vlen:= 1.0 / Sqrt(M(2,1) * M(2,1) +
M(2,2) * M(2,2) +
M(2,3) * M(2,3));
M(2,1):= M(2,1) * vlen;
M(2,2):= M(2,2) * vlen;
M(2,3):= M(2,3) * vlen;
M(3,1):= M(1,2) * M(2,3) - M(1,3) * M(2,2);
M(3,2):= M(1,3) * M(2,1) - M(1,1) * M(2,3);
M(3,3):= M(1,1) * M(2,2) - M(1,2) * M(2,1);
end Re_Orthonormalize;
type Matrix_44 is array(0..3,0..3) of aliased Real; -- for GL.MultMatrix
pragma Convention(Fortran, Matrix_44); -- GL stores matrices columnwise
M: Matrix_44;
-- M is a global variable for a clean 'Access and for setting once 4th dim
pM: constant GL.doublePtr:= M(0,0)'Unchecked_Access;
procedure Multiply_GL_Matrix( A: Matrix_33 ) is
begin
for i in 1..3 loop
for j in 1..3 loop
M(i-1,j-1):= A(i,j);
-- Funny deformations...
-- if j=2 then
-- M(i-1,j-1):= 0.5 * A(i,j);
-- end if;
end loop;
end loop;
GL.MultMatrixd(pM);
end Multiply_GL_Matrix;
procedure Set_GL_Matrix( A: Matrix_33 ) is
begin
GL.LoadIdentity;
Multiply_GL_Matrix( A );
end Set_GL_Matrix;
begin
for i in 0..2 loop
M(i,3):= 0.0;
M(3,i):= 0.0;
end loop;
M(3,3):= 1.0;
end GLOBE_3D.Math;
GLOBE_3D: Ada library for real-time 3D rendering.
Ada programming.