====== Добавляем анимацию ======
===== Определение параметров =====
Сначала определим параметры отображения окна:\\
glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
GLUT_DOUBLE - двойной буфер
===== Способ анимации =====
Теперь, надо определить каким способом будет проводиться анимация: через некоторый промежуток времени (с помощью таймера) или управлением с клавиатуры/мыши/других устройств.
==== Управление таймером ====
glutTimerFunc(20, @OnTimer, 0);
Каждые 20 мс будет вызываться обработчик событий таймера OnTimer.
Опишем его:
procedure OnTimer(value: Integer); cdecl;
begin
glutPostRedisplay; // обновляем окно
glutTimerFunc(20, @OnTimer, 0);
end;
==== Управление клавиатурой ====
Слежение за специальными клавишами делается процедурой //glutSpecialFunc()//\\
glutSpecialFunc (@SpecialKeyboard);
Опишем обрабочик событий //SpecialKeyboard//:
procedure SpecialKeyboard(key, x,y: longint); cdecl;
begin
case key of
GLUT_KEY_UP:
begin
MoveForward;
glutPostRedisplay();
end;
GLUT_KEY_DOWN:
begin
MoveBack;
glutPostRedisplay();
end;
GLUT_KEY_LEFT :
begin
MoveLeft;
glutPostRedisplay();
end;
GLUT_KEY_RIGHT :
begin
MoveRight;
glutPostRedisplay();
end;
end;
end;
end;
Процедура //glutPostRedisplay()// немедленно вызовет процедуру прорисовки объекта.
В процедуре обновления окна теперь заменяем //glFlush()// на //glutSwapBuffers()//.
==== Анимация в реальном времени ====
Ей занимается процедура glutIdleFunc()\\
glutIdleFunc(@idle);
Idle - это то, что должно происходить "вхолостую". Как правило, это всякие расчёты.
Опишем обработчик событий idle() :
procedure idle(); cdecl;
begin
{расчёты, ...}
glutPostRedisplay();
end;
===== Примеры =====
==== с обработкой клавиатуры ====
**planet.pas**
(***
<< Planet demo >>
***)
{$apptype GUI}
{$mode objfpc}
Uses
GL, GLU, GLUT;
const
year: integer = 0;
day: integer = 0;
var
oglWin : integer;
procedure init();
begin
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_FLAT);
end;
procedure display(); cdecl;
begin
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glPushMatrix();
glutWireSphere(1.0,20,16);
glRotatef(year,0.0,1.0,0.0);
(* draw sun *)
glTranslatef(2.0,0.0,0.0);
glRotatef(day,0.0,1.0,0.0);
glutWireSphere(0.2,10,8);
glPopMatrix();
(* draw smaller planet *)
glutSwapBuffers();
end;
procedure reshape(w: integer; h: integer); cdecl;
begin
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, w / h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0);
end;
procedure kbd(key: byte; x,y: longint); cdecl;
begin
case Chr(key) of
'd':
begin
day:= (day+10) mod 360;
glutPostRedisplay();
end;
'D':
begin
day:= (day-10) mod 360;
glutPostRedisplay();
end;
'y':
begin
year:= (year+5) mod 360;
glutPostRedisplay();
end;
'Y':
begin
year:= (year-5) mod 360;
glutPostRedisplay();
end;
#27:
begin
glutDestroyWindow (oglWin);
halt(0);
end;
end;
end;
begin
glutInit (@argc,argv);
glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
oglWin := glutCreateWindow('Planet demo');
init();
glutDisplayFunc(@display);
glutReshapeFunc(@reshape);
glutKeyboardFunc(@kbd);
glutMainLoop();
end.
==== с обработкой в реальном времени ====
function FMod(a,b: glFloat): glFloat;
var
x: Integer;
begin
x := Trunc (a / b);
result := a - b * x;
end;
procedure idle(); cdecl;
begin
angle1:= fmod (angle1+0.8, 360.0);
angle2:= fmod (angle2+1.1, 360.0);
s += 0.5;
glutPostRedisplay();
end;