Программа реализует пример переключения камеры между объектами, привязка камеры к объекту.
Рисунок 1. Пример работы программы
Код проекта:
unit ogl_p17_u1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, dglOpenGL, ExtCtrls, Math, DGlut; type TForm1 = class(TForm) tmr1: TTimer; procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormResize(Sender: TObject); procedure tmr1Timer(Sender: TObject); private { Private declarations } public h_RC: HGLRC; // Контекст рендеринга h_DC: HDC; // Контекст устройства procedure AttachCameraToCube; procedure AttachCameraToCube2; procedure ReturnCameraToOrigPos; procedure InitGL; procedure DrawGLScene; procedure UpdateCamera; procedure HandleKeys; procedure DrawCube; procedure DrawCube2; procedure DrawTrack; procedure BuildFont; procedure glPrint(text: string); { Public declarations } end; var Form1: TForm1; CubePos: array [0..2] of GLfloat = (0, 0, 0); // Позиция куба Cube2Pos: array [0..2] of GLfloat = (0, 0, 0); // Позиция куба 2 Cube2PosCount: GLfloat = 1.0; Cube2Rot: GLfloat = 0.0; Cube2Speed: GLfloat = 1.0; CubeRot: GLfloat = 0.0; // Угол вращения куба CamPos: array [0..2] of GLfloat = (0, 5, 10); // Позиция камеры CamPitch: GLfloat; // Углы поворота камеры MoveSpeed: GLfloat = 0.1; // Скорость перемещения CamPosFlag: GLbyte; const CAM_FREE = 0; CAM_CUBE1 = 1; CAM_CUBE2 = 2; FONT_BASE = 1000; implementation {$R *.dfm} procedure TForm1.BuildFont; var h_Font: HFONT; begin h_Font := CreateFont( -16, 0, 0, 0, FW_NORMAL, 0, 0, 0, RUSSIAN_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE or DEFAULT_PITCH, 'Arial' ); SelectObject(h_DC, h_Font); wglUseFontBitmaps(h_DC, 0, 256, FONT_BASE); DeleteObject(h_Font); end; procedure TForm1.glPrint(text: string); begin glListBase(FONT_BASE); glCallLists(Length(text), GL_UNSIGNED_BYTE, PAnsiChar(AnsiString(text))); end; procedure TForm1.AttachCameraToCube; begin CamPos[0] := CubePos[0] + 3; CamPos[1] := CubePos[1] + 4; CamPos[2] := CubePos[2] + 5; end; procedure TForm1.AttachCameraToCube2; begin CamPos[0] := Cube2Pos[0] + 3; CamPos[1] := Cube2Pos[1] + 4; CamPos[2] := Cube2Pos[2] + 5; end; procedure TForm1.ReturnCameraToOrigPos; begin CamPos[0] := 0; CamPos[1] := 5; CamPos[2] := 10; end; procedure TForm1.InitGL; begin InitOpenGL; h_DC := GetDC(Handle); h_RC := CreateRenderingContext(h_DC, [opDoubleBuffered], 32, 24, 8, 0, 0, 0); ActivateRenderingContext(h_DC, h_RC); if Assigned(wglSwapIntervalEXT) then wglSwapIntervalEXT(1); glClearColor(0.0, 0.0, 0.0, 1.0); // Чёрный фон glEnable(GL_DEPTH_TEST); // Включение теста глубины glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPerspective(45.0, 640/480, 0.1, 100.0); // Настройка перспективы glMatrixMode(GL_MODELVIEW); BuildFont; end; procedure TForm1.UpdateCamera; begin glLoadIdentity; case CamPosFlag of CAM_FREE: // Исходная позиция gluLookAt(CamPos[0], CamPos[1], CamPos[2], 0, 0, 0, 0, 1, 0); CAM_CUBE1: // Следим за первым кубом gluLookAt(CamPos[0], CamPos[1], CamPos[2], CubePos[0], CubePos[1], CubePos[2], 0, 1, 0); CAM_CUBE2: // Следим за вторым кубом gluLookAt(CamPos[0], CamPos[1], CamPos[2], Cube2Pos[0], Cube2Pos[1], Cube2Pos[2], 0, 1, 0); end; end; procedure TForm1.HandleKeys; var Angle: GLfloat; begin if GetAsyncKeyState(VK_F1) < 0 then begin CamPosFlag := CAM_CUBE1; AttachCameraToCube; end; if GetAsyncKeyState(VK_F2) < 0 then begin CamPosFlag := CAM_CUBE2; AttachCameraToCube2; end; if GetAsyncKeyState(VK_F3) < 0 then begin CamPosFlag := CAM_FREE; ReturnCameraToOrigPos; end; if GetAsyncKeyState(VK_UP) < 0 then begin CubePos[2] := CubePos[2] - MoveSpeed; if CamPosFlag = CAM_CUBE1 then AttachCameraToCube; end; if GetAsyncKeyState(VK_DOWN) < 0 then begin CubePos[2] := CubePos[2] + MoveSpeed; if CamPosFlag = CAM_CUBE1 then AttachCameraToCube; end; if GetAsyncKeyState(VK_LEFT) < 0 then begin CubePos[0] := CubePos[0] - MoveSpeed; if CamPosFlag = CAM_CUBE1 then AttachCameraToCube; end; if GetAsyncKeyState(VK_RIGHT) < 0 then begin CubePos[0] := CubePos[0] + MoveSpeed; if CamPosFlag = CAM_CUBE1 then AttachCameraToCube; end; CubeRot := CubeRot + 2.0; // Вращение if CubeRot >= 360 then CubeRot := 0; // Движение и вращение второго куба Cube2PosCount := Cube2PosCount + Cube2Speed; if Cube2PosCount >= 360 then Cube2PosCount := 0; // Всегда обновляем позицию второго куба Angle := DegToRad(Cube2PosCount); Cube2Pos[0] := 5*Cos(Angle); Cube2Pos[1] := 0.5; Cube2Pos[2] := 5*Sin(Angle); Cube2Rot := Cube2Rot + 3.0; // Независимое вращение if Cube2Rot >= 360 then Cube2Rot := 0; end; procedure TForm1.DrawCube; begin glColor3f(0, 0, 1); // Синий цвет glPushMatrix; glTranslatef(CubePos[0], CubePos[1], CubePos[2]); glRotatef(CubeRot, 0, 1, 0); // Вращение вокруг Y glutSolidCube(1.0); // Используем GLUT для простоты glPopMatrix; end; procedure TForm1.DrawCube2; begin glColor3f(1, 0, 1); // Фиолетовый цвет glPushMatrix; glTranslatef(Cube2Pos[0], Cube2Pos[1], Cube2Pos[2]); glRotatef(Cube2Rot, 0, 1, 0); glutSolidCube(1.0); glPopMatrix; end; procedure TForm1.DrawTrack; var i: Integer; begin glColor3f(1, 1, 0); // Жёлтый цвет glBegin(GL_LINE_STRIP); for i := 0 to 360 do glVertex3f(5*Cos(DegToRad(i)), 0, 5*Sin(DegToRad(i))); glEnd; end; procedure TForm1.DrawGLScene; begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity; UpdateCamera; HandleKeys; DrawTrack; DrawCube; DrawCube2; // Сохраняем текущую матрицу glPushMatrix; // Переключаемся в 2D режим для текста glMatrixMode(GL_PROJECTION); glPushMatrix; glLoadIdentity; gluOrtho2D(0, ClientWidth, ClientHeight, 0); // 2D проекция glMatrixMode(GL_MODELVIEW); glPushMatrix; glLoadIdentity; // Отключаем тест глубины для текста glDisable(GL_DEPTH_TEST); // Устанавливаем цвет текста glColor3f(1.0, 1.0, 1.0); // Белый цвет // Рисуем текст glRasterPos2f(10, 20); glPrint('F1 - Синий куб'); glRasterPos2f(10, 40); glPrint('F2 - Розовый куб'); glRasterPos2f(10, 60); glPrint('F3 - Вся сцена'); // Восстанавливаем настройки glEnable(GL_DEPTH_TEST); glPopMatrix; // MODELVIEW glMatrixMode(GL_PROJECTION); glPopMatrix; // PROJECTION glMatrixMode(GL_MODELVIEW); glPopMatrix; // исходная матрица SwapBuffers(h_DC); end; procedure TForm1.FormDestroy(Sender: TObject); begin wglMakeCurrent(0, 0); wglDeleteContext(h_RC); ReleaseDC(Handle, h_DC); end; procedure TForm1.FormCreate(Sender: TObject); begin DoubleBuffered := False; InitGL; KeyPreview := True; Visible := True; tmr1.Interval := 16; CamPosFlag := 0; Cube2PosCount := 0; end; procedure TForm1.FormResize(Sender: TObject); begin glViewport(0, 0, ClientWidth, ClientHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPerspective(45.0, ClientWidth/ClientHeight, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); end; procedure TForm1.tmr1Timer(Sender: TObject); begin DrawGLScene; end; end.
Комментариев нет:
Отправить комментарий