I've a question about using OpenGL from Delphi. My intention is to draw a grid of n rows and n columns in a form. i want the cells in the grid to be square like this image:
This is the code I use to create this grid:
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, Winapi.OpenGL, System.SysUtils,
System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Vcl.Menus;
type
TfrmMain = class(TForm)
PopupMenu: TPopupMenu;
mnuDrawGrid: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure mnuDrawGridClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
private
glDC: HDC;
oldW: Integer;
oldH: Integer;
glContext: HGLRC;
errorCode: GLenum;
openGLReady: Boolean;
procedure DisegnaLinea(const aX1, aY1, aX2, aY2: Double; aSpessore,
aOffSet: Integer);
procedure DisegnaTabellone(const aNumRighe, aNumColonne: SmallInt);
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
{ Gestione form -------------------------------------------------------------- }
// OpenGL initialization
procedure TfrmMain.FormCreate(Sender: TObject);
var
pfd: TPixelFormatDescriptor;
formatIndex: Integer;
begin
FillChar(pfd, SizeOf(pfd), 0);
with pfd do
begin
nSize := SizeOf(pfd);
nVersion := 1;
dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL;
iPixelType := PFD_TYPE_RGBA;
cColorBits := 24;
cDepthBits := 32;
iLayerType := PFD_MAIN_PLANE;
end;
glDC := GetDC(Handle);
formatIndex := ChoosePixelFormat(glDC, @pfd);
if formatIndex = 0 then
raise Exception.Create('Choose pixel format failed ' + IntToStr(GetLastError));
if not SetPixelFormat(glDC, formatIndex, @pfd) then
raise Exception.Create('Set pixel forma failed ' + IntToStr(GetLastError));
glContext := wglCreateContext(glDC);
if not glContext = 0 then
raise Exception.Create('Create context failed ' + IntToStr(GetLastError));
if not wglMakeCurrent(glDC, glContext) then
raise Exception.Create('Make current failsed ' + IntToStr(GetLastError));
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(0.0, ClientWidth, 0.0, ClientHeight, 0.0, 1.0);
oldW := ClientWidth;
oldH := ClientHeight;
openGLReady := True;
end;
// OpenGL destruction
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
wglMakeCurrent(Canvas.Handle, 0);
wglDeleteContext(glContext);
end;
// Form resize
procedure TfrmMain.FormResize(Sender: TObject);
begin
if not openGLReady then
exit;
glViewport(0, 0, ClientWidth, ClientHeight);
errorCode := glGetError;
if errorCode <> GL_NO_ERROR then
raise Exception.Create('Form resize: ' + gluErrorString(errorCode));
if (ClientWidth <> oldW) and (ClientHeight <> oldH) then
DisegnaTabellone(10, 10);
oldW := ClientWidth;
oldH := ClientHeight;
end;
{ Gestione menu -------------------------------------------------------------- }
// Menu option grid drawing
procedure TfrmMain.mnuDrawGridClick(Sender: TObject);
begin
DisegnaTabellone(10, 10);
end;
{ OpenGL --------------------------------------------------------------------- }
// Draw a line at aX1, aY1 to aX2, aY2 coordinates
procedure TfrmMain.DisegnaLinea(const aX1, aY1, aX2, aY2: Double; aSpessore,
aOffSet: Integer);
begin
glEnable(GL_LINE_SMOOTH);
glLineWidth(aSpessore);
glBegin(GL_LINES);
glVertex2f(aX1, aY1);
glVertex2f(aX2, aY2);
glEnd;
end;
// Grid design
procedure TfrmMain.DisegnaTabellone(const aNumRighe, aNumColonne: SmallInt);
const
vOffSet = 20;
var
idx: SmallInt;
pX: Double;
pY: Double;
incX: Double;
incY: Double;
hPos: Double;
hWidth: Double;
widthArea: Integer;
heightArea: Integer;
aspectRatio: Double;
begin
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
widthArea := ClientWidth;
heightArea := ClientHeight;
aspectRatio := widthArea / heightArea;
pY := vOffSet / 2;
incY := (heightArea - vOffSet) / aNumRighe;
pX := (widthArea - aNumColonne * incY) / 2;
hPos := pX;
hWidth := hPos + aNumColonne * incY;
incX := incY;
// Draw vertical lines
for idx := 0 to aNumColonne do begin
DisegnaLinea(pX, vOffSet / 2, pX, heightArea - vOffSet / 2, 3, 0);
pX := pX + incX;
end;
// Draw horizontal lines
for idx := 0 to aNumRighe do begin
DisegnaLinea(hPos, pY, hWidth, pY, 3, 0);
pY := pY + incY;
end;
glFlush;
end;
end.
I initialize the pixel format description in the FormCreate event and Ive created a routine called by a popup menu in order to draw the grid. In this routine I make same calculation because I want the grid cells to be square as I said. So I take the height of the form (ClientHeight) and I divide it for the number of rows I need: in this case 10 plus i'ce a little offset in order to have a margin on the top and bottom of the form. Then I calculate the width of the grid for a perfet square. It works well but the problem come when I resize the form. My intension is to draw a new grid smaller or larger according to the form dimensions, but this is only my intention because the grid does'nt mantein the correct aspet ratio and is drawn in a bad manner as ou can see in the following picure:
I can't understand where is the error in my code. I'm nwe at OpenGL so can someone help me?
Eros


DisegnaLinea()- Ripi2