unit Models;

interface

uses Windows, SysUtils, Math3D, GL, GLu, GLext, WGLext, GLtools, VertexArray;

type
  TModel = class
  protected
    FVertexArray        : TVertexArray;

    FVertexBase         : cardinal;
    FVertexNum          : cardinal;
    FIndexBase          : cardinal;
    FIndexNum           : cardinal;

    FVertex             : PVertexArrayType;
    FColor0             : PColorArrayType;
    FColor1             : PColorArrayType;
    FNormal             : PNormalArrayType;
    FTexCoord           : PTexCoordArrayType;
    FIndex              : PIndexArrayType;

    FCurrentVertex      : cardinal;
    FCurrentIndex       : cardinal;

    FPrimitiveMode      : cardinal;
  public
    FReferences         : integer;
    FIdentifier         : string;
    constructor Create(va: TVertexArray); virtual;
    destructor Destroy; override;
    function Init(numver, numidx: cardinal): boolean; virtual;
    procedure Vertex(x, y, z, w: single); overload; virtual;
    procedure Vertex(v: TVector4); overload; virtual;
    procedure Vertex(i: cardinal; x, y, z, w: single); overload; virtual;
    procedure Vertex(i: cardinal; v: TVector4); overload; virtual;
    procedure Color0(r, g, b, a: single); overload; virtual;
    procedure Color0(c: TVector4); overload; virtual;
    procedure Color0(i: cardinal; r, g, b, a: single); overload; virtual;
    procedure Color0(i: cardinal; c: TVector4); overload; virtual;
    procedure Color1(r, g, b, a: single); overload; virtual;
    procedure Color1(c: TVector4); overload; virtual;
    procedure Color1(i: cardinal; r, g, b, a: single); overload; virtual;
    procedure Color1(i: cardinal; c: TVector4); overload; virtual;
    procedure Normal(x, y, z: single); overload; virtual;
    procedure Normal(n: TVector3); overload; virtual;
    procedure Normal(i: cardinal; x, y, z: single); overload; virtual;
    procedure Normal(i: cardinal; n: TVector3); overload; virtual;
    procedure TexCoord(s, t, r, q: single); overload; virtual;
    procedure TexCoord(t: TVector4); overload; virtual;
    procedure TexCoord(i: cardinal; s, t, r, q: single); overload; virtual;
    procedure TexCoord(i: cardinal; t: TVector4); overload; virtual;
    procedure Index(idx: cardinal); overload; virtual;
    procedure Index(i, idx: cardinal); overload; virtual;
    procedure BeginModel(mode: cardinal); virtual;
    procedure EndModel; virtual;
    procedure Render; virtual;
    property NrVertex: cardinal read FVertexNum;
    property NrIndex: cardinal read FIndexNum;
    property VertexArray: TVertexArray read FVertexArray write FVertexArray;
  end;

implementation

constructor TModel.Create;
begin
  inherited Create;

  FVertexArray     := va;
end;

destructor TModel.Destroy;
begin
  inherited Destroy;
end;

function TModel.Init;
begin
  FVertexBase        := FVertexArray.AllocVertex(numver);
  FVertexNum         := numver;
  FIndexBase         := FVertexArray.AllocIndex(numidx);
  FIndexNum          := numidx;
  result := true;
end;

procedure TModel.Vertex(x, y, z, w: single);
begin
  FVertex[FCurrentVertex] := Vector4(x, y, z, w);
  inc(FCurrentVertex);
end;

procedure TModel.Vertex(v: TVector4);
begin
  FVertex[FCurrentVertex] := v;
  inc(FCurrentVertex);
end;

procedure TModel.Vertex(i: cardinal; x, y, z, w: single);
begin
  FVertex[i] := Vector4(x, y, z, w);
end;

procedure TModel.Vertex(i: cardinal; v: TVector4);
begin
  FVertex[i] := v;
end;

procedure TModel.Color0(r, g, b, a: single);
begin
  FColor0[FCurrentVertex] := Vector4(r, g, b, a);
end;

procedure TModel.Color0(c: TVector4);
begin
  FColor0[FCurrentVertex] := c;
end;

procedure TModel.Color0(i: cardinal; r, g, b, a: single);
begin
  FColor0[i] := Vector4(r, g, b, a);
end;

procedure TModel.Color0(i: cardinal; c: TVector4);
begin
  FColor0[i] := c;
end;

procedure TModel.Color1(r, g, b, a: single);
begin
  FColor1[FCurrentVertex] := Vector4(r, g, b, a);
end;

procedure TModel.Color1(c: TVector4);
begin
  FColor1[FCurrentVertex] := c;
end;

procedure TModel.Color1(i: cardinal; r, g, b, a: single);
begin
  FColor1[i] := Vector4(r, g, b, a);
end;

procedure TModel.Color1(i: cardinal; c: TVector4);
begin
  FColor1[i] := c;
end;

procedure TModel.Normal(x, y, z: single);
begin
  FNormal[FCurrentVertex] := Vector3(x, y, z);
end;

procedure TModel.Normal(n: TVector3);
begin
  FNormal[FCurrentVertex] := n;
end;

procedure TModel.Normal(i: cardinal; x, y, z: single);
begin
  FNormal[i] := Vector3(x, y, z);
end;

procedure TModel.Normal(i: cardinal; n: TVector3);
begin
  FNormal[i] := n;
end;

procedure TModel.TexCoord(s, t, r, q: single);
begin
  FTexCoord[FCurrentVertex] := Vector4(s, t, r, q);
end;

procedure TModel.TexCoord(t: TVector4);
begin
  FTexCoord[FCurrentVertex] := t;
end;

procedure TModel.TexCoord(i: cardinal; s, t, r, q: single);
begin
  FTexCoord[i] := Vector4(s, t, r, q);
end;

procedure TModel.TexCoord(i: cardinal; t: TVector4);
begin
  FTexCoord[i] := t;
end;

procedure TModel.Index(idx: cardinal);
begin
  FIndex[FCurrentIndex] := idx + FVertexBase;
  inc(FCurrentIndex);
end;

procedure TModel.Index(i, idx: cardinal);
begin
  FIndex[i] := idx + FVertexBase;
end;

procedure TModel.BeginModel;
begin
  FVertexArray.Unlock;

  FVertex            := @FVertexArray.Vertex[FVertexBase];
  FColor0            := @FVertexArray.Color0[FVertexBase];
  FColor1            := @FVertexArray.Color1[FVertexBase];
  FNormal            := @FVertexArray.Normal[FVertexBase];
  FTexCoord          := @FVertexArray.TexCoord[0][FVertexBase];
  FIndex             := @FVertexArray.Index[FIndexBase];

  FCurrentVertex     := 0;
  FCurrentIndex      := 0;

  FPrimitiveMode     := mode;
end;

procedure TModel.EndModel;
begin
  FVertexArray.Lock;
end;

procedure TModel.Render;
begin
  FVertexArray.Render(FPrimitiveMode, FIndexNum, FIndexBase);
end;

end.
