Сначала определим параметры отображения окна:
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;