My TPolygon Class: (MPL license)

Code:
unit Polygon;

interface

uses DGLOpenGL;

type
TPoint = packed record
  x: single;
  y: single;
  z: single;
  r: single;
  g: single;
  b: single;
  a: single;
end;

TPolygon = class
private
  FPoints: array of TPoint; //polygon point
  FVertex: array of TPoint; //triangulated data
  FColor: TPoint;
  FCount: integer;
  FVertexCount: integer;
  FTesselated: boolean;
  procedure SetPoint(I: integer; Value: TPoint);
  procedure AddVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
  function GetPoint(I: integer): TPoint;
  function GetCount(): integer;
  procedure tessBegin(which: GLenum);
  procedure tessEnd();
  procedure tessVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
public
  constructor Create();
  destructor Destroy();
  procedure SetColor(R: single; G: single; B: single;A: single);
  procedure Add(X: single; Y: single); overload;
  procedure Add(X: single; Y: single; Z: single); overload;
  procedure Add(X: single; Y: single; Z: single; R: single; G: single; B: single; A: single); overload;
  procedure Render();
  procedure Tesselate();
  property Points[I: integer]: TPoint read GetPoint write SetPoint;
  property Count: integer read GetCount;
end;

implementation

type
     TGLArrayd6 = array[0..5] of GLDouble;
     PGLArrayd6 = ^TGLArrayd6;
     TGLArrayvertex4 = array[0..3] of PGLArrayd6;
     PGLArrayvertex4 = ^TGLArrayvertex4;
     PGLArrayf4 = ^TGLArrayf4;

threadvar
  PolygonClass: TPolygon;

procedure TPolygon.SetColor(R: single; G: single; B: single;A: single);
begin
  FColor.r := R;
  FColor.g := G;
  FColor.b := B;
  FColor.a := A;
end;

procedure TPolygon.tessBegin(which: GLenum);
begin
    glBegin(which);
end;

procedure TPolygon.tessEnd();
begin
    glEnd();
end;

procedure TPolygon.tessVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
begin
    glcolor3f(r,g,b);
    glVertex3f(x,y,z);
end;

procedure TPolygon.AddVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
begin
    FVertexCount := FVertexCount + 1;
    SetLength(FVertex, FVertexCount);

    FVertex[FVertexCount-1].R := R;
    FVertex[FVertexCount-1].G := G;
    FVertex[FVertexCount-1].B := B;

    FVertex[FVertexCount-1].X := X;
    FVertex[FVertexCount-1].Y := Y;
    FVertex[FVertexCount-1].Z := Z;
end;

constructor TPolygon.Create();
begin
  inherited Create();
  FCount := 0;
  FVertexCount := 0;
  FTesselated := false;
  FColor.R := 0.0;
  FColor.G := 0.0;
  FColor.B := 0.0;
  FColor.A := 0.0;
end;

destructor TPolygon.Destroy();
begin
  FTesselated := false;
  FCount := 0;
  FVertexCount := 0;
  SetLength(FPoints, FCount);
  SetLength(FVertex, FVertexCount);
  inherited Destroy;
end;

procedure TPolygon.SetPoint(I: integer; Value: TPoint);
begin
  FTesselated := false; //check first on changed values
  FPoints[I] := Value;
end;

function TPolygon.GetPoint(I: integer): TPoint;
begin
  result := FPoints[I];
end;

function TPolygon.GetCount(): integer;
begin
  result := FCount;
end;

procedure TPolygon.Add(X: single; Y: single);
begin
  FTesselated := false;
  FCount := FCount + 1;
  SetLength(FPoints, FCount);
  FPoints[FCount-1].X := X;
  FPoints[FCount-1].Y := Y;
  FPoints[FCount-1].Z := 0.0;
  FPoints[FCount-1].R := FColor.R;
  FPoints[FCount-1].G := FColor.G;
  FPoints[FCount-1].B := FColor.B;
  FPoints[FCount-1].A := FColor.A;
end;

procedure TPolygon.Add(X: single; Y: single; Z: single);
begin
  FTesselated := false;
  FCount := FCount + 1;
  SetLength(FPoints, FCount);
  FPoints[FCount-1].X := X;
  FPoints[FCount-1].Y := Y;
  FPoints[FCount-1].Z := Z;
  FPoints[FCount-1].R := FColor.R;
  FPoints[FCount-1].G := FColor.G;
  FPoints[FCount-1].B := FColor.B;
  FPoints[FCount-1].A := FColor.A;
end;

procedure TPolygon.Add(X: single; Y: single; Z: single; R: single; G: single; B: single; A: single);
begin
  FTesselated := false;
  FCount := FCount + 1;
  SetLength(FPoints, FCount);
  FPoints[FCount-1].X := X;
  FPoints[FCount-1].Y := Y;
  FPoints[FCount-1].Z := Z;
  FPoints[FCount-1].R := R;
  FPoints[FCount-1].G := G;
  FPoints[FCount-1].B := B;
  FPoints[FCount-1].A := A;
end;

Procedure TPolygon.Render();
var
  loop: integer;
begin
  if FTesselated = false then Tesselate;

  glbegin(GL_TRIANGLES);
  for loop:=0 to FVertexCount-1 do
  begin
    glcolor3f(FVertex[loop].R,FVertex[loop].G,FVertex[loop].B);
    glvertex3f(FVertex[loop].X,FVertex[loop].Y,FVertex[loop].Z);
  end;
  glend;
end;

procedure TPolygon.Tesselate();
var
  loop: integer;
  tess: pointer;
  test: TGLArrayd3;
  pol: PGLArrayd6;

  MyTest: string;

procedure iTessBeginCB(which: GLenum); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
begin
  //PolygonClass.tessBegin(which);
end;

procedure iTessEndCB(); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
begin
  //PolygonClass.tessEnd();
end;

procedure iTessEdgeCB(flag: GLboolean; lpContext: pointer); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
begin
      //just do nothing to force GL_TRIANGLES !!!
end;

procedure iTessVertexCB(data: PGLArrayd6); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
begin
  //PolygonClass.tessVertex(data[0], data[1], data[2], data[3], data[4], data[5],0);
  PolygonClass.AddVertex(data[0], data[1], data[2], data[3], data[4], data[5],0);
end;


procedure iTessCombineCB(newVertex : PGLArrayd6; neighborVertex : Pointer;
                      neighborWeight : Pointer; var outData : Pointer); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
var
  vertex: PGLArrayd6;
  loop: integer;
  colorloop: integer;
  color: double;
begin
  new(vertex);

  vertex[0] := newVertex^[0];
  vertex[1] := newVertex^[1];
  vertex[2] := newVertex^[2];

  for colorloop := 3 to 5 do
  begin
    vertex[colorloop] := 0.0;
    for loop:=0 to 3 do
    begin
      if PGLArrayf4&#40;neighborWeight&#41;^&#91;loop&#93; <> 0 then
      begin
        vertex&#91;colorloop&#93; &#58;= vertex&#91;colorloop&#93; +
             PGLArrayf4&#40;neighborWeight&#41;^&#91;loop&#93; *
             PGLArrayvertex4&#40;neighborVertex&#41;^&#91;loop&#93;&#91;colorloop&#93;
      end;
    end;
  end;

  // return output data &#40;vertex coords and others&#41;
  outData&#58;= vertex;
end;

begin
  PolygonClass &#58;= Self;

  tess &#58;= gluNewTess&#40;&#41;;

  gluTessCallback&#40;tess, GLU_TESS_BEGIN, @iTessBeginCB &#41;;
  gluTessCallback&#40;tess, GLU_TESS_END, @iTessEndCB&#41;;
  gluTessCallback&#40;tess, GLU_TESS_VERTEX, @iTessVertexCB&#41;;
  gluTessCallback&#40;tess, GLU_TESS_COMBINE, @iTessCombineCB&#41;;  //does not work for font?
  gluTessCallback&#40;tess, GLU_TESS_EDGE_FLAG_DATA, @iTessEdgeCB&#41;; //force triangles

  gluTessProperty&#40;tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO &#41;;

  gluTessBeginPolygon&#40;tess, nil&#41;;                   // with NULL data
  gluTessBeginContour&#40;tess&#41;;

  for loop &#58;= 0 to FCount-1 do
  begin
      new&#40;pol&#41;;
      pol&#91;3&#93;&#58;=FPoints&#91;loop&#93;.R; //color
      pol&#91;4&#93;&#58;=FPoints&#91;loop&#93;.G;
      pol&#91;5&#93;&#58;=FPoints&#91;loop&#93;.B;

      pol&#91;0&#93;&#58;=FPoints&#91;loop&#93;.X;
      pol&#91;1&#93;&#58;=FPoints&#91;loop&#93;.Y;
      pol&#91;2&#93;&#58;=0;

      test&#91;0&#93; &#58;= pol&#91;0&#93;;
      test&#91;1&#93; &#58;= pol&#91;1&#93;;
      test&#91;2&#93; &#58;= pol&#91;2&#93;;
      gluTessVertex&#40;tess, test, pol&#41;;
  end;

  gluTessEndContour&#40;tess&#41;;
  gluTessEndPolygon&#40;tess&#41;;
  gluDeleteTess&#40;tess&#41;;        // delete after tessellation

  PolygonClass &#58;= nil;
  FTesselated &#58;= true;
end;

end.