unit Frost.Resources;

interface

uses
  _Geometry,
  Frost.Utils,
  Frost.Renderers;

type
TResources = class
    private
    public                    
      function LoadMMSMesh(FileName: String; Scale: Single = 1): TMesh;
      constructor Create();
  end;

implementation

{$REGION 'TResources'}
constructor TResources.Create();
begin

end;

function TResources.LoadMMSMesh(FileName: String; Scale: Single = 1): TMesh;
var
  F: File of Char;
  i, j, z, l: Cardinal; //counters
  S: string;
  a: Char;
  Mode: Byte; //trigger  // 0-none       1-Vertex num(vc}
                         // 2-Faces num  3-textures num
                         // 4-normals
  cnt: Byte;             // 0- num       1-x 2-y 3-z
                         // 4-a 5-b 6-c

  VertexFrames: array of TVertexes;
  Vertex:   TVertexes;
  Normals:  TNormals;
  Textures: TTextures;
  Faces:    TFaces;
  TexFaces: TFaces;

  FVertex:   TVertexes;
  FNormals:  TNormals;
  FTextures: TTextures;
  FFaces:    TFaces;
      
  num_Vertex:cardinal;
  num_Faces:cardinal;
  num_Tex_Vertex:cardinal;
  num_anim:cardinal;

  Normal: TVector3;

{$REGION 'Set val'}
procedure set_val(var s:string;M,c:byte;var i:Cardinal; var j:Cardinal;var z:Cardinal; var L:Cardinal);
begin
 if (S<>'') then
  case m of
   1:case c of
      0:begin     {vertex nums}
         num_Vertex := StrToInt(S);
         num_anim := L;
         SetLength(VertexFrames, num_Anim+1);
         SetLength(VertexFrames[L], num_Vertex+1);
         SetLength(Normals, num_Vertex+1);
         i:=0;
         z:=0;
        end;
      1:begin VertexFrames[L][i].X := StrToFloat(S); end; {x}
      2:begin VertexFrames[L][i].Y := StrToFloat(S); end; {y}
      3:begin VertexFrames[L][i].Z := StrToFloat(S);
        if (i<num_Vertex) then i:=i+1;end; {z}
      4:begin Faces[j][0]:=StrToInt(S)-1; end; {a}
      5:begin Faces[j][1]:=StrToInt(S)-1; end; {b}
      6:begin Faces[j][2]:=StrToInt(S)-1;
        if (j<num_Faces) then j:=j+1;
        end; {c}
      10:begin      {faces num}
          num_Faces:=StrToInt(S)-1;       {face count in program begin from 0!!!!!!!!!!!!!!!!!1}
          SetLength(Faces,num_Faces+1);
          j:=0;
         end;
     end;
   3:case c of
      0:begin      {textures num}
         num_Tex_Vertex := StrToInt(S);
         SetLength(Textures,num_Tex_Vertex+1);
         SetLength(TexFaces,num_Faces+1);
         i:=0;j:=0;
         L:=L+1;
        end;
      1:begin Textures[i].X:=StrToFloat(S); end; {x}
      2:begin Textures[i].Y:=StrToFloat(S);
        if (i<num_Tex_Vertex) then i:=i+1;end; {y}
      4:begin TexFaces[j][0]:=StrToInt(S)-1; end; {a}
      5:begin TexFaces[j][1]:=StrToInt(S)-1; end; {b}
      6:begin TexFaces[j][2]:=StrToInt(S)-1;
        if (j<num_Faces) then j:=j+1;end;{c}
     end;
   4:case c of
      1:begin Normals[i].X:=StrToFloat(S); end; {x}
      2:begin Normals[i].Y:=StrToFloat(S); end; {y}
      3:begin Normals[i].Z:=StrToFloat(S);
        if (i<num_Vertex) then i:=i+1;end; {z}
     end;
  end;
 S:='';
end;
{$ENDREGION}
begin
 mode := 0;
 cnt := 0;
 i := 0;
 j := 0;
 z := 0;
 l := 0;
 AssignFile(F,FileName);
 Reset(F);
 S := '';
 Repeat
  a := 'q';
  Read(F,a);
  case a of
   'e','E','0','1'..'9','-': S := S + a;{numbers (with minus and point for float)}
   '.',',': S := S + '.';
   'X','x': begin set_val(s, Mode, cnt, i, j, z, l); cnt :=1; end;
   'Y','y': begin set_val(s, Mode, cnt, i, j, z, l); cnt :=2; end;
   'Z','z': begin set_val(s, Mode, cnt, i, j, z, l); cnt :=3; end; {float vertex and texture coords}
   'A','a': begin set_val(s, Mode, cnt, i, j, z, l); cnt :=4; end;
   'B','b': begin set_val(s, Mode, cnt, i, j, z, l); cnt :=5; end;
   'C','c': begin set_val(s, Mode, cnt, i, j, z, l); cnt :=6; end; {int faces and textures for them}
   'V','v': begin set_val(s, Mode, cnt, i, j, z, l); mode := 1; cnt := 0; end;{prefix col vertex}
   'F','f': begin set_val(s, Mode, cnt, i, j, z, l); mode := 1; cnt := 10; end;{prefix col faces}
   'N','n': begin set_val(s, Mode, cnt, i, j, z, l); if (mode <> 4) then i := 0; mode := 4; cnt := 0; end;{prefix normal}
   'T','t': begin set_val(s, Mode, cnt, i, j, z, l); mode := 3; cnt := 0; end;{prefix texture}
   'q','Q': begin set_val(s, Mode, cnt, i, j, z, l); cnt := 0; mode := 3; end;{part of 'Tex' word}
   else     begin set_val(s, Mode, cnt, i, j, z, l); cnt := 0; end;
  end;
  Until Eof(F);
  CloseFile(F);
  for i := 0 to num_Vertex do
    Normals[i] := Normals[i].Normalize;
  SetLength(Vertex, num_vertex + 1);
  for i := 0 to Length(Vertex) - 1 do
    Vertex[i] :=  VertexFrames[0][i] * Scale;

  SetLength(FVertex, (num_Faces + 1) * 3);
  SetLength(FTextures, (num_Faces + 1) * 3);
  SetLength(FNormals, (num_Faces + 1) * 3);
  SetLength(FFaces, (num_Faces + 1));

  for i := 0 to num_Faces do
  begin
    FFaces[i] := Face(i * 3 + 0, i * 3 + 1, i * 3 + 2);
    FVertex[i * 3 + 0] := Vertex[Faces[i][0]];
    FVertex[i * 3 + 1] := Vertex[Faces[i][1]];
    FVertex[i * 3 + 2] := Vertex[Faces[i][2]];
    Normal := GetNormal(Vertex[Faces[i][0]], Vertex[Faces[i][1]], Vertex[Faces[i][2]]);
    FNormals[i * 3 + 0] := Normal;
    FNormals[i * 3 + 1] := Normal;
    FNormals[i * 3 + 2] := Normal; 
    FTextures[i * 3 + 0] := Textures[TexFaces[i][0]];
    FTextures[i * 3 + 1] := Textures[TexFaces[i][1]];
    FTextures[i * 3 + 2] := Textures[TexFaces[i][2]];
  end;

  Result := TMesh.Create(FFaces, FVertex, FTextures, FNormals);
  SetLength(VertexFrames, 0);
  SetLength(Vertex, 0);
  SetLength(Textures, 0);
  SetLength(Normals, 0);
  SetLength(Faces, 0);
end;
{$ENDREGION}

end.
