unit Main;
interface
uses
OpenGL, Windows, SysUtils, Classes, Controls, Forms, StdCtrls, ComCtrls, ExtCtrls;
const
MaxLevelOfDetail = 100;
NumberOfControlPoints = 4;
type
TSineIndex = record
Position : Integer;
Speed : Integer;
Travel : GLFloat;
end;
TPoint = record
X, Y, Z : GLFloat;
end;
TfrmMain = class(TForm)
Timer1 : TTimer;
pOGL : TPanel;
procedure FormCreate (Sender : TObject);
procedure Timer1Timer (Sender : TObject);
procedure FormKeyDown (Sender: TObject; var Key: Word; Shift: TShiftState);
private
function GetPointOnCurve (ControlPoint1, ControlPoint2, ControlPoint3, ControlPoint4 : TPoint; CurvePoint : GLFloat) : TPoint;
procedure Draw;
procedure SetupControlPoints;
public
end;
var
frmMain : TfrmMain;
LevelOfDetail : Integer = 50;
ControlPoints : array[0..4,0..NumberOfControlPoints - 1] of TPoint;
SineTable : array[0..360] of GLFloat;
SineIndices : array[0..3] of TSineIndex;
implementation
procedure glBindTexture (Target : GLEnum; Texture : GLUInt); stdcall; external OpenGL32;
procedure glGenTextures (N : GLSizeI; var Textures : GLUInt); stdcall; external OpenGL32;
{$R *.DFM}
procedure SetupPixelFormat ( DC : HDC
);
const
PFD : TPIXELFORMATDESCRIPTOR = (
nSize : SizeOf (TPIXELFORMATDESCRIPTOR); nVersion : 1;
dwFlags : PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER;
iPixelType : PFD_TYPE_RGBA;
cColorBits : 24; cRedBits : 0; cRedShift : 0; cGreenBits : 0; cGreenShift : 0;
cBlueBits : 0; cBlueShift : 0; cAlphaBits : 0; cAlphaShift : 0; cAccumBits : 0;
cAccumRedBits : 0; cAccumGreenBits : 0; cAccumBlueBits : 0; cAccumAlphaBits : 0;
cDepthBits : 16; cStencilBits : 0; cAuxBuffers : 0; iLayerType : PFD_MAIN_PLANE;
bReserved : 0; dwLayerMask : 0; dwVisibleMask : 0; dwDamageMask : 0);
var
PixelFormat : Integer;
begin
PixelFormat := ChoosePixelFormat (DC,@PFD);
if (PixelFormat = 0) then
begin
Exit;
end;
if (SetPixelFormat (DC,PixelFormat,@PFD) <> True) then
begin
Exit;
end;
end;
procedure TfrmMain.FormCreate ( Sender : TObject
);
const
DEG2RAD = 3.14159 / 180;
var
DegInRad : GLFloat;
DC : HDC;
RC : HGLRC;
Loop : Integer;
begin
Caption := 'DpM: OpenGL Bezier Curve (Level Of Detail: ' + IntToStr (LevelOfDetail) + ')';
Width := Screen.Width;
Height := Screen.Height;
DC := GetDC (pOGL.Handle);
SetupPixelFormat (DC);
RC := wglCreateContext (DC);
wglMakeCurrent (DC,RC);
SetUpControlPoints;
glClearColor (0,0,0,1);
glLineWidth (14);
glMap1f (GL_MAP1_VERTEX_3,0,1,3,4,@ControlPoints[0]);
glEnable (GL_MAP1_VERTEX_3);
glShadeModel (GL_SMOOTH);
for Loop := 0 to 360 do
begin
DegInRad := Loop * DEG2RAD;
SineTable[Loop] := Sin (DegInRad);
end;
SineIndices[0].Position := 0;
SineIndices[0].Speed := 1;
SineIndices[0].Travel := 1.6;
SineIndices[1].Position := 0;
SineIndices[1].Speed := 1;
SineIndices[1].Travel := 0.1;
SineIndices[2].Position := 40;
SineIndices[2].Speed := 2;
SineIndices[2].Travel := 0.4;
SineIndices[3].Position := 200;
SineIndices[3].Speed := 1;
SineIndices[3].Travel := 2.6;
end;
procedure TfrmMain.Draw;
procedure DisplayBackground;
begin
glMatrixMode (GL_PROJECTION);
glLoadIdentity;
glOrtho (0,pOGL.Width,0,pOGL.Height,-10,10);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity;
glColor3f (1,1,1);
glBindTexture (GL_TEXTURE_2D,BackgroundTexture);
glBegin (GL_QUADS);
glTexCoord2f (0,0);
glVertex2f (0,0);
glTexCoord2f (1,0);
glVertex2f (pOGL.Width,0);
glTexCoord2f (1,1);
glVertex2f (pOGL.Width,pOGL.Height);
glTexCoord2f (0,1);
glVertex2f (0,pOGL.Height);
glEnd;
end;
procedure DisplayStreamers;
var
ControlPointLoop, Loop : Integer;
begin
glMatrixMode (GL_PROJECTION);
glLoadIdentity;
gluPerspective (45,pOGL.Width / pOGL.Height,1,100);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity;
glTranslatef (0,0,-10);
for ControlPointLoop := 0 to High (ControlPoints) do
begin
case ControlPointLoop of
0 : glColor4f (0,0.5,1,1);
1 : glColor4f (0,1,0.5,1);
2 : glColor4f (1,0,0.5,1);
3 : glColor4f (1,0.5,1,1);
4 : glColor4f (1,1,0.5,1);
end;
case ControlPointLoop of
0 : begin
ControlPoints[ControlPointLoop][0].Y := SineTable[SineIndices[0].Position] * SineIndices[0].Travel;
ControlPoints[ControlPointLoop][1].Y := SineTable[SineIndices[1].Position] * SineIndices[1].Travel;
ControlPoints[ControlPointLoop][2].Y := SineTable[SineIndices[2].Position] * SineIndices[2].Travel;
ControlPoints[ControlPointLoop][3].Y := 3 + SineTable[SineIndices[3].Position] * SineIndices[3].Travel;
end;
1 : begin
ControlPoints[ControlPointLoop][1].Y := SineTable[SineIndices[0].Position] * SineIndices[0].Travel;
ControlPoints[ControlPointLoop][3].Y := 3 + SineTable[SineIndices[1].Position] * SineIndices[1].Travel;
ControlPoints[ControlPointLoop][0].Y := SineTable[SineIndices[2].Position] * SineIndices[2].Travel;
ControlPoints[ControlPointLoop][2].Y := SineTable[SineIndices[3].Position] * SineIndices[3].Travel;
end;
2 : begin
ControlPoints[ControlPointLoop][3].Y := 3 + SineTable[SineIndices[0].Position] * SineIndices[0].Travel;
ControlPoints[ControlPointLoop][0].Y := SineTable[SineIndices[1].Position] * SineIndices[1].Travel;
ControlPoints[ControlPointLoop][2].Y := SineTable[SineIndices[2].Position] * SineIndices[2].Travel;
ControlPoints[ControlPointLoop][1].Y := SineTable[SineIndices[3].Position] * SineIndices[3].Travel;
end;
3 : begin
ControlPoints[ControlPointLoop][2].Y := SineTable[SineIndices[0].Position] * SineIndices[0].Travel;
ControlPoints[ControlPointLoop][0].Y := SineTable[SineIndices[1].Position] * SineIndices[1].Travel;
ControlPoints[ControlPointLoop][3].Y := 3 + SineTable[SineIndices[2].Position] * SineIndices[2].Travel;
ControlPoints[ControlPointLoop][1].Y := SineTable[SineIndices[3].Position] * SineIndices[3].Travel;
end;
4 : begin
ControlPoints[ControlPointLoop][2].Y := SineTable[SineIndices[0].Position] * SineIndices[0].Travel;
ControlPoints[ControlPointLoop][1].Y := SineTable[SineIndices[1].Position] * SineIndices[1].Travel;
ControlPoints[ControlPointLoop][0].Y := SineTable[SineIndices[2].Position] * SineIndices[2].Travel;
ControlPoints[ControlPointLoop][3].Y := 3 + SineTable[SineIndices[3].Position] * SineIndices[3].Travel;
end;
end;
glMap1f (GL_MAP1_VERTEX_3,0,1,3,4,@ControlPoints[ControlPointLoop]);
{ Draw the actual segements of the Bezier curve. }
glBegin (GL_LINE_STRIP);
for Loop := 0 to LevelOfDetail do
begin
{ How do I really know what X, Y and Z this is? }
glEvalCoord1f (Loop / LevelOfDetail);
end;
glEnd;
{ Reset the Indices into the SineTable each time it is required. }
for Loop := Low (SineIndices) to High (SineIndices) do
begin
Inc (SineIndices[Loop].Position,SineIndices[Loop].Speed);
if (SineIndices[Loop].Position > High (SineTable)) then
begin
SineIndices[Loop].Position := Low (SineTable);
end;
end;
end;
end;
begin
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
DisplayStreamers;
SwapBuffers (wglGetCurrentDC);
end;
procedure TfrmMain.Timer1Timer ( Sender : TObject
);
begin
Draw;
end;
function TfrmMain.GetPointOnCurve ( ControlPoint1, ControlPoint2, ControlPoint3, ControlPoint4 : TPoint;
CurvePoint : GLFloat
) : TPoint;
var
V1, V2, V3 : GLFloat;
Returning : TPoint;
begin
V1 := 1 - CurvePoint;
V2 := V1 * V1 * V1;
V3 := CurvePoint * CurvePoint * CurvePoint;
Returning.X := V2 * ControlPoint1.X + 3 * CurvePoint * V1 * V1 * ControlPoint2.X + 3 * CurvePoint * CurvePoint * V1 * ControlPoint3.X + V3 * ControlPoint4.X;
Returning.Y := V2 * ControlPoint1.Y + 3 * CurvePoint * V1 * V1 * ControlPoint2.Y + 3 * CurvePoint * CurvePoint * V1 * ControlPoint3.Y + V3 * ControlPoint4.Y;
Returning.Z := V2 * ControlPoint1.Z + 3 * CurvePoint * V1 * V1 * ControlPoint2.Z + 3 * CurvePoint * CurvePoint * V1 * ControlPoint3.Z + V3 * ControlPoint4.Z;
GetPointOnCurve := Returning;
end;
procedure TfrmMain.FormKeyDown ( Sender : TObject;
var Key : Word;
Shift : TShiftState
);
begin
if (Key = VK_DOWN) then
begin
if (LevelOfDetail > 1) then
begin
Dec (LevelOfDetail);
Caption := 'DpM: OpenGL Bezier Curve (Level Of Detail: ' + IntToStr (LevelOfDetail) + ')';
end;
end else
if (Key = VK_UP) then
begin
if (LevelOfDetail < MaxLevelOfDetail) then
begin
Inc (LevelOfDetail);
Caption := 'DpM: OpenGL Bezier Curve (Level Of Detail: ' + IntToStr (LevelOfDetail) + ')';
end;
end else
if (Key = VK_RETURN) then
begin
end else
if (Key = VK_SPACE) then
begin
end;
end;
procedure TfrmMain.SetupControlPoints;
begin
{ Set up the control points for the Bezier curve... }
ControlPoints[0][0].X := -17;
ControlPoints[0][0].Y := -2;
ControlPoints[0][0].Z := 0;
ControlPoints[0][1].X := -2;
ControlPoints[0][1].Y := 6;
ControlPoints[0][1].Z := 0;
ControlPoints[0][2].X := 0;
ControlPoints[0][2].Y := -2;
ControlPoints[0][2].Z := 0;
ControlPoints[0][3].X := 18;
ControlPoints[0][3].Y := 4;
ControlPoints[0][3].Z := 0;
{ Set up the control points for the Bezier curve... }
ControlPoints[1][0].X := -12;
ControlPoints[1][0].Y := -0;
ControlPoints[1][0].Z := 0;
ControlPoints[1][1].X := -4;
ControlPoints[1][1].Y := 6;
ControlPoints[1][1].Z := 0;
ControlPoints[1][2].X := -2;
ControlPoints[1][2].Y := -2;
ControlPoints[1][2].Z := 0;
ControlPoints[1][3].X := 10;
ControlPoints[1][3].Y := 4;
ControlPoints[1][3].Z := 0;
{ Set up the control points for the Bezier curve... }
ControlPoints[2][0].X := -14;
ControlPoints[2][0].Y := 0;
ControlPoints[2][0].Z := 0;
ControlPoints[2][1].X := 0;
ControlPoints[2][1].Y := 0;
ControlPoints[2][1].Z := 0;
ControlPoints[2][2].X := 4;
ControlPoints[2][2].Y := 0;
ControlPoints[2][2].Z := 0;
ControlPoints[2][3].X := 11;
ControlPoints[2][3].Y := 0;
ControlPoints[2][3].Z := 0;
{ Set up the control points for the Bezier curve... }
ControlPoints[3][0].X := -13;
ControlPoints[3][0].Y := 0;
ControlPoints[3][0].Z := 0;
ControlPoints[3][1].X := -8;
ControlPoints[3][1].Y := 0;
ControlPoints[3][1].Z := 0;
ControlPoints[3][2].X := 8;
ControlPoints[3][2].Y := 0;
ControlPoints[3][2].Z := 0;
ControlPoints[3][3].X := 19;
ControlPoints[3][3].Y := 0;
ControlPoints[3][3].Z := 0;
{ Set up the control points for the Bezier curve... }
ControlPoints[4][0].X := -16;
ControlPoints[4][0].Y := 0;
ControlPoints[4][0].Z := 0;
ControlPoints[4][1].X := -10;
ControlPoints[4][1].Y := 0;
ControlPoints[4][1].Z := 0;
ControlPoints[4][2].X := -2;
ControlPoints[4][2].Y := 0;
ControlPoints[4][2].Z := 0;
ControlPoints[4][3].X := 21;
ControlPoints[4][3].Y := 0;
ControlPoints[4][3].Z := 0;
end;
end.