unit l_model_v2;

interface

uses
 Windows, OpenGL, err,
 l_math, l_gl;

type
 //-- Модель --//
 TMesh_v2 = object
   V_Count : integer;
   F_Count : integer;
   Vertex  : array of TVector;   // Вершины
   Normal  : array of TVector;   // Нормали
   Face    : array of TFace;     // Грани
 end;

 TModel_v2 = object
   Loaded  : boolean;
   Meshes  : integer;
   Mesh    : array of TMesh_v2;
   procedure Init;
   procedure Clear;
   function LoadFromFile(const FileName: string): boolean;
   procedure Render;
 end;

var
 gun_xmd   : TModel_v2;
 zenit_xmd : TModel_v2;

implementation

uses
 l_game;

procedure TModel_v2.Init;
begin
Meshes := 0;
Mesh   := nil;
Clear;
end;

procedure TModel_v2.Clear;
var
 i : integer;
begin
Loaded  := false;
for i := 0 to Meshes - 1 do
 with Mesh[i] do
  begin
  V_Count := 0;
  F_Count := 0;
  Vertex  := nil;
  Normal  := nil;
  Face    := nil;
  end;
Meshes := 0;
Mesh   := nil;
end;

function TModel_v2.LoadFromFile(const FileName: string): boolean;
var
 xmd   : File of Byte;
 Magic : array [0..3] of Char;
 i, j  : integer;
 obj   : integer;
 n     : TVector;
begin
Clear;
Loaded := false;
Result := false;
 try
 AssignFile(xmd, FileName);
 Reset(xmd);
 BlockRead(xmd, Magic, 4);
 if Magic <> 'XMD2' then Exit;
 BlockRead(xmd, Meshes, 4);
 SetLength(Mesh, Meshes);
 for obj := 0 to Meshes - 1 do
  with Mesh[obj] do
   begin
   BlockRead(xmd, V_Count, 4);
   BlockRead(xmd, F_Count, 4);
   SetLength(Vertex, V_Count);
   SetLength(Face, F_Count);
   BlockRead(xmd, Vertex[0], V_Count*SizeOf(TVector));
   BlockRead(xmd, Face[0], F_Count*SizeOf(TFace));
   // Расчёт нормалей (они в массиве вершин)
   SetLength(Normal, V_Count);
   FillChar(Normal[0], V_Count*SizeOf(TVector), 0);
   for i := 0 to F_Count - 1 do
    begin
    n := P_Normal(Vertex[Face[i][0]],
                  Vertex[Face[i][1]],
                  Vertex[Face[i][2]]);
    for j := 0 to 2 do
     Normal[Face[i][j]] := V_Add(Normal[Face[i][j]], n);
    end;
   for i := 0 to V_Count - 1 do
    Normal[i] := V_Normalize(Normal[i]);
   end;
 CloseFile(xmd);

 Loaded := true;
 Result := true;
 except
 end;
end;

procedure TModel_v2.Render;
var
 i : integer;
begin
if not Loaded then Exit;
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
for i := 0 to Meshes - 1 do
 with Mesh[i] do
  begin
  glNormalPointer(GL_FLOAT, 0, @Normal[0]);
  glVertexPointer(3, GL_FLOAT, 0, @Vertex[0]);
  glDrawElements(GL_TRIANGLES, F_Count*3, GL_UNSIGNED_SHORT, @Face[0]);
  end;
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
end;

end.
