OpenGL i obsługa wielu klawiszy na raz

0

Na podstawie tutoriala OpenGL do Lazarusa (http://wiki.freepascal.org/OpenGL_Tutorial) i tej stronki: http://www.swiftless.com/tutorials/opengl/keyboard.html chciałem zrobić obsługę wielu klawiszy na raz i napisałem coś takiego:

program firstprogram;

{$mode objfpc}{$H+}

uses
  gl, glu, glut;

const
  AppWidth = 640;
  AppHeight = 480;

var
  KeyStates    : array[0..255] of boolean;
  i            : integer;
  ScreenWidth,
  ScreenHeight : Integer;

procedure Init;
begin
  glClearColor(0.18, 0.20, 0.66, 0);
end;

procedure ProcessKeys;
begin
  if KeyStates[27] then
    Halt(0);
end;

procedure Keyboard(Key: Byte; X, Y: Longint); cdecl;
begin
  KeyStates[Key] := true;
end;

procedure KeyboardUp(Key: Byte; X, Y: Longint); cdecl;
begin
  KeyStates[Key] := false;
end;

procedure Draw; cdecl;
begin
  ProcessKeys;

  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glutSwapBuffers;
end;

procedure ReSize(Width, Height: Integer); cdecl;
begin
  if Height = 0 then
    Height := 1;

  glViewport(0, 0, Width, Height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(45, Width / Height, 0.1, 1000);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;

procedure glutInitPascal(ParseCmdLine: Boolean);
var
  Cmd: array of PChar;
  CmdCount, I: Integer;
begin
  if ParseCmdLine then
    CmdCount := ParamCount + 1
  else
    CmdCount := 1;
  SetLength(Cmd, CmdCount);
  for I := 0 to CmdCount - 1 do
    Cmd[I] := PChar(ParamStr(I));
  glutInit(@CmdCount, @Cmd);
end;

begin
  for i := 0 to 255 do
    KeyStates[i] := false;
  glutInitPascal(True);
  glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
  glutInitWindowSize(AppWidth, AppHeight);
  ScreenWidth := glutGet(GLUT_SCREEN_WIDTH);
  ScreenHeight := glutGet(GLUT_SCREEN_HEIGHT);
  glutInitWindowPosition((ScreenWidth - AppWidth) div 2, (ScreenHeight - AppHeight) div 2);
  glutCreateWindow('OpenGL Tutorial :: First Program');

  Init;

  glutDisplayFunc(@Draw);
  glutReshapeFunc(@ReSize);
  glutKeyboardFunc(@Keyboard);
  glutKeyboardUpFunc(@KeyboardUp);

  glutMainLoop;
end.

No i jak widać z kodu przy naciśnięciu klawisza ESC program powinien się zakończyć a tak się nie dzieje. Gdy do funkcji Keyboard lub KeyboardUp dodam if Key = 27 then Halt(0); to wtedy program się wyłącza. Gdy funkcję Keyboard napiszę w ten sposób:

procedure Keyboard(Key: Byte; X, Y: Longint); cdecl;
begin
  KeyStates[Key] := true;
  if KeyStates[27] then Halt(0);
end;

To program również się zamknie.
Pomyślałem, że może to przez sam kod ESC i przerobiłem KeyProcess na if KeyStates[ord('q')] then Halt(0); jednak też nie działa mimo że jak wpiszę if Key = ord('q') then Halt(0); w Keyboard lub KeyboardUp to program się zamyka.

Ktoś może mi powiedzieć gdzie leży błąd albo nakierować na rozwiązanie?

2

bo funkcja display jest tutaj wywoływana tylko raz
żeby program się zamknął musiałbyś trzymać Escape, a potem zrobić coś z oknem żeby się odrysowało (na przykład zakryć innym i odkryć z powrotem, lub zmienić jego rozmiar) i wykonała się funkcja odrysowania w której masz obsługę klawiatury

potrzebujesz włożyć obsługę klawiatury w funkcję która się wykonuje cały czas, czyli albo do glutIdleFunc, albo do glutTimerFunc, albo ewentualnie kazać programowi odrysować okno poprzez glutPostRedisplay po wykryciu naciśnięcia każdego klawisza

0

Ah no prawda zapomniałem o dopisaniu glutIdleFunc(@Draw); (podobno takie coś zwiększa wydajność). Dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1