Смекни!
smekni.com

Отчет по OpenGL (стр. 2 из 2)

Для задания различных преобразований объектов сцены в OpenGL используются операции над матрицами, при этом различают три типа матриц: видовая, проекций и текстуры. Все они имеют размер 4x4. Видовая матрица определяет преобразования объекта в мировых координатах, такие как параллельный перенос, изменение масштаба и поворот. Матрица проекций задает как будут проецироваться трехмерные объекты на плоскость экрана (в оконные координаты), а матрица текстуры определяет наложение текстуры на объект.

Для того чтобы выбрать, какую матрицу надо изменить, используется команда

void glMatrixMode(GLenum mode)

вызов которой со значением параметра mode равным GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE включает режим работы с видовой, проекций и матрицей текстуры соответственно. Для вызова команд, задающих матрицы того или иного типа необходимо сначала установить соответствующий режим.

Для определения элементов матрицы текущего типа вызывается команда

void glLoadMatrix[f d](GLtype *m)

где m указывает на массив из 16 элементов типа float или double в соответствии с названием команды, при этом сначала в нем должен быть записан первый столбец матрицы, затем второй, третий и четвертый.

Команда

void glLoadIdentity(void)

заменяет текущую матрицу на единичную. Часто нужно сохранить содержимое текущей матрицы для дальнейшего использования, для чего используют команды

void glPushMatrix(void)

void glPopMatrix(void)

Они записывают и восстанавливают текущую матрицу из стека, причем для каждого типа матриц стек свой. Для видовых матриц его глубина равна как минимум 32, а для двух оставшихся типов как минимум 2.

Для умножения текущей матрицы слева на другую матрицу используется команда

void glMultMatrix[f d](GLtype *m)

где m должен задавать матрицу размером 4x4 в виде массива с описанным расположением данных. Однако обычно для изменения матрицы того или иного типа удобно использовать специальные команды, которые по значениям своих параметров создают нужную матрицу и перемножают ее с текущей. Чтобы сделать текущей созданную матрицу, надо перед вызовом этой команды вызвать glLoadIdentity().

В целом, для отображения трехмерных объектов сцены в окно приложения используется следующая последовательность действий:

Координаты объекта => Видовые координаты => Усеченные координаты => Нормализованные координаты => Оконные координаты

В OpenGL существуют ортографическая (параллельная) и перспективная проекция. Первый тип проекции может быть задан командами

void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)

void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)

Первая команда создает матрицу проекции в усеченный объем видимости (параллелограмм видимости) в левосторонней системе координат. Параметры команды задают точки (left, bottom, -near) и (right, top, -near), которые отвечают левому нижнему и правому верхнему углам окна вывода. Параметры near и far задают расстояние до ближней и дальней плоскостей отсечения по дальности от точки (0,0,0) и могут быть отрицательными.

Во второй команде, в отличие от первой, значения near и far устанавливаются равными –1 и 1 соответственно.

Перспективная проекция определяется командой

void gluPerspective(GLdouble angley, GLdouble aspect, GLdouble znear, GLdouble zfar)

которая задает усеченный конус видимости в левосторонней системе координат. Параметр angley определяет угол видимости в градусах по оси у и должен находиться в диапазоне от 0 до 180. Угол видимости вдоль оси x задается параметром aspect, который обычно задается как отношение сторон области вывода. Параметры zfar и znear задают расстояние от наблюдателя до плоскостей отсечения по глубине и должны быть положительными. Чем больше отношение zfar/znear, тем хуже в буфере глубины будут различаться расположенные рядом поверхности, так как по умолчанию в него будет записываться ‘сжатая’ глубина в диапазоне от 0 до 1.

Задание и исходный код

Задание: рисунок «КУБ».

unit mgl;

interface

uses

Windows, Messages, Classes, Graphics, Forms, ExtCtrls, OpenGL, StdCtrls,

Controls, SysUtils, Spin, Menus, Dialogs;

type

TForm1 = class(TForm)

procedure FormCreate(Sender: TObject);

procedure FormResize(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormKeyPress(Sender: TObject; var Key: Char);

private

DC : HDC;

hrc : HGLRC;

Angle, AngleX, AngleY, AngleZ: GLfloat;

procedure DrawScene;

procedure InitializeRC;

procedure SetDCPixelFormat;

protected

// Обработка сообщения WM_PAINT - аналог события OnPaint

procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;

end;

var

Form1: TForm;

ch, c, i: integer;

s: string;

ShowHelp: boolean=true;

implementation

{$R *.DFM}

const

// массив свойств материала

MaterialColor: Array [0..3] of GLfloat = (0.5, 0.0, 1.0, 1.0);

// Процедура инициализации источника цвета

procedure TForm1.InitializeRC;

begin

glEnable(GL_DEPTH_TEST); // разрешаем тест глубины

glEnable(GL_LIGHTING); // разрешаем работу с освещенностью

glEnable(GL_LIGHT0); // включаем источник света 0

end;

// Отрисовка картинки

procedure TForm1.DrawScene;

begin

// очистка буфера цвета и буфера глубины

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

// трехмерность

glMatrixMode(GL_MODELVIEW);

glLoadIdentity;

glTranslatef(0.0, 0.0, -8.0); // влево/вправо, вверх/вниз, назад/вперед

glRotatef(AngleX, 1.0, 0.0, 0.0); // поворот на угол X

glRotatef(AngleY, 0.0, 1.0, 0.0); // поворот на угол Y

glRotatef(AngleZ, 0.0, 0.0, 1.0); // поворот на угол Z

// Шесть сторон куба

glBegin(GL_POLYGON);

glNormal3f(0.0, 0.0, 1.0);

glVertex3f(1.0, 1.0, 1.0);

glVertex3f(-1.0, 1.0, 1.0);

glVertex3f(-1.0, -1.0, 1.0);

glVertex3f(1.0, -1.0, 1.0);

glEnd;

glBegin(GL_POLYGON);

glNormal3f(0.0, 0.0, -1.0);

glVertex3f(1.0, 1.0, -1.0);

glVertex3f(1.0, -1.0, -1.0);

glVertex3f(-1.0, -1.0, -1.0);

glVertex3f(-1.0, 1.0, -1.0);

glEnd;

glBegin(GL_POLYGON);

glNormal3f(-1.0, 0.0, 0.0);

glVertex3f(-1.0, 1.0, 1.0);

glVertex3f(-1.0, 1.0, -1.0);

glVertex3f(-1.0, -1.0, -1.0);

glVertex3f(-1.0, -1.0, 1.0);

glEnd;

glBegin(GL_POLYGON);

glNormal3f(1.0, 0.0, 0.0);

glVertex3f(1.0, 1.0, 1.0);

glVertex3f(1.0, -1.0, 1.0);

glVertex3f(1.0, -1.0, -1.0);

glVertex3f(1.0, 1.0, -1.0);

glEnd;

glBegin(GL_POLYGON);

glNormal3f(0.0, 1.0, 0.0);

glVertex3f(-1.0, 1.0, -1.0);

glVertex3f(-1.0, 1.0, 1.0);

glVertex3f(1.0, 1.0, 1.0);

glVertex3f(1.0, 1.0, -1.0);

glEnd;

glBegin(GL_POLYGON);

glNormal3f(0.0, -1.0, 0.0);

glVertex3f(-1.0, -1.0, -1.0);

glVertex3f(1.0, -1.0, -1.0);

glVertex3f(1.0, -1.0, 1.0);

glVertex3f(-1.0, -1.0, 1.0);

glEnd;

SwapBuffers(DC); // конец работы

end;

// обычные действия OpenGL, Создание окна

procedure TForm1.FormCreate(Sender: TObject);

begin

Angle:=0;

AngleX:=30;

AngleY:=-30;

AngleZ:=0;

c:=1;

DC:=GetDC(Handle);

SetDCPixelFormat;

hrc:=wglCreateContext(DC);

wglMakeCurrent(DC, hrc);

InitializeRC;

// свойства материала - лицевые стороны - рассеянный

// цвет материала и диффузное отражение материала - значения из массива

glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,@MaterialColor);

end;

// Установка формата пикселей

procedure TForm1.SetDCPixelFormat;

var

nPixelFormat: integer;

pfd: TPixelFormatDescriptor;

begin

FillChar(pfd, SizeOf(pfd), 0);

with pfd do

begin

nSize :=sizeof(pfd);

nVersion:=1;

dwFlags :=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or

PFD_DOUBLEBUFFER;

iPixelType:=PFD_TYPE_RGBA;

cColorBits:=24; // 24

cDepthBits:=32; // 32

iLayerType:= PFD_MAIN_PLANE;

end;

nPixelFormat := ChoosePixelFormat(DC, @pfd);

SetPixelFormat(DC, nPixelFormat, @pfd);

end;

// Изменение размеров окна

procedure TForm1.FormResize(Sender: TObject);

begin

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

gluPerspective(30.0, Width/Height, 1.0, 10.0);

glViewport(0, 0, Width, Height);

glMatrixMode(GL_MODELVIEW);

InvalidateRect(Handle, nil, False);

end;

// Обработка сообщения WM_PAINT, рисование окна

procedure TForm1.WMPaint(var Msg: TWMPaint);

var

ps: TPaintStruct;

begin

BeginPaint(Handle, ps);

DrawScene;

EndPaint(Handle, ps);

end;

// Конец работы программы

procedure TForm1.FormDestroy(Sender: TObject);

begin

wglMakeCurrent(0, 0);

wglDeleteContext(hrc);

ReleaseDC(Handle, DC);

end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);

begin

if ord(key)=27 then Application.Terminate; // Esc

FormResize(nil);

end;

end.


Рисунок «Куб»


Использованные источники

1. Тихомиров Ю. Программирование трехмерной графики. СПб., BHV 1998.

2. Visual Introduction in OpenGL, Siggraph’98.

3. The OpenGL graphics system: a specification (version 1.1).

4. The OpenGL Utility Toolkit (GLUT) Programming Interface, API version 3, specification.