unit MX1;
/////////////////////////////////
// Morphing Model Animetion unit
// by XProger
/////////////////////////////////
interface

uses
  Windows, OpenGL, eXgine, l_math;

type
  TModel = class
    constructor Create(const Name: string);
   private
    Texture  : TTexture;
    FPS      : Integer;   
    K_Count  : Integer;
    V_Count  : Integer;
    F_Count  : Integer;
    T_Count  : Integer;
    Vertex   : array of TVector;
    Face     : array of TFace;
    TexCoord : array of TVector2D;
    TexFace  : array of TFace;
   public
    procedure Render;
  end;

implementation

constructor TModel.Create(const Name: string);
var
  F : File;
begin
  AssignFile(F, Name + '.mx1');
  Reset(F, 1);
// Чтение заголовка
  BlockRead(F, V_Count, SizeOf(V_Count));
  BlockRead(F, F_Count, SizeOf(F_Count));
  BlockRead(F, T_Count, SizeOf(T_Count));
  BlockRead(F, K_Count, SizeOf(K_Count));
  BlockRead(F, FPS, SizeOf(FPS));
// Выделение памяти под данные модели
  SetLength(Vertex, K_Count * V_Count);
  SetLength(Face, F_Count);
  SetLength(TexCoord, T_Count);
  SetLength(TexFace, F_Count);
// Грани и текстурные координаты
  BlockRead(F, Face[0], F_Count * SizeOf(TFace));
  BlockRead(F, TexCoord[0], T_Count * SizeOf(TVector2D));
  BlockRead(F, TexFace[0], F_Count * SizeOf(TFace));
// Загрузка анимации вершин (вершины для всех кадров хранятся в одном массиве)
// сдвиг индекса вершин до следующего кадра = V_Count
  BlockRead(F, Vertex[0], K_Count * V_Count * SizeOf(TVector));
  CloseFile(F);
// Загрузка текстуры (eXgine функция)
  Texture := tex.Load(PChar(Name + '.jpg'));
end;

procedure TModel.Render;
var
  i, j   : Integer;
  lf, nf : Integer;
  dt, t  : Single;
begin
  dt := 1000 div FPS;                       // длительность одного кадра
  lf := trunc(GetTickCount/dt) mod K_Count; // вычисляем предыдущий кадр
  nf := (lf + 1) mod K_Count;               // и следующий
  t  := frac(GetTickCount/dt);              // временной коэффициент

  tex.Enable(Texture); // Включение текстуры (eXgine функция)

// отрисовка
  glBegin(GL_TRIANGLES);
  for i := 0 to F_Count - 1 do
    for j := 0 to 2 do
      with V_Lerp(Vertex[lf * V_Count + Face[i][j]],
                  Vertex[nf * V_Count + Face[i][j]], t) do // интерполируем вершину
      begin
        glTexCoord2fv(@TexCoord[TexFace[i][j]]);
        glVertex3f(X, Y, Z); // X Y Z - координаты интерполированной вершины
      end;
  glEnd;
end;


end.
