unit sgOpenGL;

interface

uses
  sgConsts, Math, Extrusion;

const
  pi_180: extended = 3.1415926535897932384626433832795/180;
  _2pi: extended = 2 * 3.1415926535897932384626433832795;
  ZERO_EPS = 0.00000000000001;

type
  TArray4s = array[0 .. 3] of single;
  PArray4s = ^TArray4s;
  TglMatrix = array [0 .. 3, 0 .. 3] of single;
  PglMatrix = ^TglMatrix;
  TglSwapMatrixes = array[boolean] of TglMatrix;
  PglSwapMatrixes = ^TglSwapMatrixes;

type
  PFPoint = ^TFPoint;

var
  glSwapMatrixes: TglSwapMatrixes;
  bCurentMatrix: boolean;

procedure IdentMatGL(A: PglMatrix);
procedure IdentSwapMatrix;
procedure MultMatrixGL(A, B, C: PglMatrix);
procedure RotateGL(Axis: TsgAxes; Angle: Extended);
procedure FixPoint(ptIn, ptOut: PArray4s; pmat: PglMatrix);
procedure Normalize(n: PFPoint);
//procedure CalcNormal(Extent: single; Vector1, Vector2, Vector3, Normal: PFPoint);
procedure CalcNormal(P1, P2, P3, N: PFPoint);
procedure ScalePoint(p, s: PArray4s);


implementation

function sr(Angle: extended): extended;
begin
  Result := sin(pi_180*Angle);
end;

function cr(Angle: extended): extended;
begin
  Result := cos(pi_180*Angle);
end;

procedure FixPoint(ptIn, ptOut: PArray4s; pmat: PglMatrix);
begin
  ptOut^[0] := ptIn^[0] * pmat^[0, 0] + ptIn^[1] * pmat^[0, 1] + ptIn^[2] * pmat^[0, 2] + pmat^[0, 3];
  ptOut^[1] := ptIn^[0] * pmat^[1, 0] + ptIn^[1] * pmat^[1, 1] + ptIn^[2] * pmat^[1, 2] + pmat^[1, 3];
  ptOut^[2] := ptIn^[0] * pmat^[2, 0] + ptIn^[1] * pmat^[2, 1] + ptIn^[2] * pmat^[2, 2] + pmat^[2, 3];
end;

procedure ScalePoint(p, s: PArray4s);
begin
  p^[0] := p^[0] * s^[0];
  p^[1] := p^[1] * s^[1];
  p^[2] := p^[2] * s^[2];
end;

procedure IdentMatGL(A: PglMatrix);
begin
  FillChar(A^, SizeOf(A^), 0);
  A^[0,0] := 1;
  A^[1,1] := 1;
  A^[2,2] := 1;
  A^[3,3] := 1;
end;

procedure IdentSwapMatrix;
begin
  IdentMatGL(@glSwapMatrixes[bCurentMatrix][0, 0]);
  IdentMatGL(@glSwapMatrixes[not bCurentMatrix][0, 0]);
end;

procedure MultMatrixGL(A, B, C: PglMatrix);
var
  I,J,K: Integer;
begin
  for I := 0 to 3 do
  begin
    for J := 0 to 3 do
    begin
      C^[I, J] := 0.0;
      for K := 0 to 2 do
        C^[I, J] := C^[I, J] + A^[I, K] * B^[K, J];
    end;
  end;
  for J := 0 to 3 do
    C^[3, J] := C^[3, J] + B^[3, J];
  C^[3, 3] := 1.0;
end;
          
procedure RotateGL(Axis: TsgAxes; Angle: Extended);
var
  vM: TglMatrix;

  procedure DoMat(A, B: Integer);
  var
    S, C: Extended;
  begin
    IdentMatGL(@vM[0, 0]);
    SinCos(Radian(Angle), S, C);
    if Axis = axisY then
      S := -S;
    vM[A, A] := C;
    vM[B, B] := C;
    vM[A, B] := S;
    vM[B, A] := -S;
    MultMatrixGL(@glSwapMatrixes[bCurentMatrix][0, 0], @vM[0, 0], @glSwapMatrixes[not bCurentMatrix][0, 0]);
    bCurentMatrix := not bCurentMatrix;
  end;

begin
  case Axis of
    axisX: DoMat(1, 2);
    axisY: DoMat(0, 2);
    axisZ: DoMat(0, 1);
  end;
end;

procedure Normalize(n: PFPoint);
var
  len: Double;
begin
  len := Sqrt((n^.x * n^.x) + (n^.y * n^.y) + (n^.z * n^.z));
  if len <> 0 then
  begin
    n^.x := n^.x / len;
    n^.y := n^.y / len;
    n^.z := n^.z / len;
  end;
end;

function Vector(const P1, P2, N: PFPoint): TFPoint;
begin
  N^.X := P1^.Y * P2^.Z - P1^.Z * P2^.Y;
  N^.Y := P1^.Z * P2^.X - P1^.X * P2^.Z;
  N^.Z := P1^.X * P2^.Y - P1^.Y * P2^.X;
end;

procedure CalcNormal(P1, P2, P3, N: PFPoint);
var
  V1, V2: TFpoint;
begin
  V1.X := P2^.X - P1^.X;
  V1.Y := P2^.Y - P1^.Y;
  V1.Z := P2^.Z - P1^.Z;

  V2.X := P3^.X - P1^.X;
  V2.Y := P3^.Y - P1^.Y;
  V2.Z := P3^.Z - P1^.Z;

  Vector(@V1, @V2, N);
  Normalize(N);
end;

end.
