Цель лекции: Научиться использовать основные примитивы OpenGL для формирования изображения.
Пример № 4.1 Пример демонстрирует формирование несвязанных отрезков.
Пример № 4.2 Пример демонстрирует формирование замкнутой ломаной.
Пример № 4.3 Пример демонстрирует формирование несвязанных треугольников.
Пример № 4.4 Пример демонстрирует формирование треугольников с общими гранями.
Пример № 4.5 Пример демонстрирует формирование треугольников с общей вершиной.
Пример № 4.6 Пример демонстрирует формирование несвязанных четырехугольников.
Пример № 4.7 Пример демонстрирует формирование четырехугольников с общими гранями.
Пример № 4.8 Пример демонстрирует формирование многоугольника.
Пример № 4.9 Пример демонстрирует построение графика функции y = z*Sin(x*n) с возможностью изменения коэффициентов n и z с помощью клавиатуры.
В OpenGL все изображения формируются из графических примитивов, основными из которых являются точки, отрезки, треугольники, четырехугольники, многоугольники. Базовым графическим примитивом для построения сложных объёмных изображений является треугольник. Такие примитивы как четырехугольники и многоугольники хотя и создаются с помощью отдельных команд, но формируются библиотекой OpenGL из набора треугольников. Необходимая детализация сложных изображений достигается за счет уменьшения размера примитивов, из которых строится изображение, и увеличения их количества.
Формирование примитива начинается с вызова команды Begin и передачи ей в качестве значения параметра mode целочисленной константы, которая определяет формируемый примитив:
Begin (mode: GLenum);
В Object Pascal для реализации команды Begin используется процедура
procedure glBegin (mode: GLenum);
Например, для формирования точек используется константа GL_POINTS, для формирования отрезков –константа GL_LINES.
В библиотеке OpenTK для реализации команды Begin используется статический метод класса GL (C#):
void Begin(BeginMode mode);
Формируемый примитив определяется с помощью элемента перечисления BeginMode. Для формирования точек используется значение этого перечисления Points, для формирования отрезков – значение Lines.
Формирование примитивов завершается с помощью команды End.
В Object Pascal эта команда реализуется с помощью процедуры:
procedure glEnd;
В библиотеке OpenTK для реализации команды End используется статический метод класса GL (C#):
void End();
Все примитивы состоят из набора вершин. Для задания расположения вершин в пространстве используются нормализованные координаты.
Координаты каждой вершины определяются с помощью команды OpenGL:
Vertex[2 3 4][s i f d]
Вызов этой команды должен выполняться межу вызовами команд Begin и End, иначе команда Vertex будет проигнорирована библиотекой.
Команда может иметь от 2 до 4 параметров. Если команда имеет три параметра, то ей передаются декартовые координаты вершин. В варианте команды с двумя параметрами они соответствуют декартовым координатам по оси OX и OY, координата по оси OZ принимается равной нулю.
В Object Pascal команда Vertex реализована набором процедур, объявление двух из них приведено ниже:
procedure glVertex2d (x,y: GLdouble); procedure glVertex3d (x,y, z: GLdouble);
В библиотеке OpenTK команда реализуется с помощью статических методов класса GL с различным числом параметров и типами данных. Объявление двух из них приведено ниже.
void Vertex2(double x, double y); void Vertex3(double x, double y, double z);
Необходимо обратить внимание на то, что для каждого вызова команды Begin должен быть соответствующий вызов команды End. Их можно сравнить с парой операторов begin и end языка Pascal, которые так же являются парными. Но в отличие от них для команд Begin и End компилятор не проверяет их парность, и эта задача ложится полностью на программиста. При несоблюдении парности вызовов команд Begin и End часто возникают довольно сложно выявляемые ошибки в формировании изображения.
Для формирования точек в качестве значения параметра mode команды Begin необходимо указать значение:
GL_POINTS в программе на Object Pascal;Points перечисления BeginMode в программе на C#.Перед формированием точек могут быть указаны их размер и определён режим сглаживания, который будет использоваться при их отображении. Эти параметры должны быть установлены перед вызовом команды Begin.
Размер точки может быть установлен с помощью команды PointSize. В Object Pascal команда реализуется с помощью процедуры:
procedure glPointSize (size: GLfloat);
В библиотеке OpenTK для этого используется статический метод класса GL (C#):
void PointSize(float size);
По умолчанию размер точки равен одному пикселу. Необходимо обратить внимание на то, что хотя координаты точки задаются в масштабе сцены, но размер точки задается в координатах устройства вывода изображения. Связано это с тем, что точки формируются на одном из последних этапов формирования изображения – на этапе растеризации.
Управление режимом сглаживания точки осуществляется с помощью команд Enable и Disable. Команда Enable включает режим сглаживания точек, команда Disable отключает его. По умолчанию режим сглаживания точек отключен.
В Object Pascal эти команды реализованы с помощью процедур:
procedure glEnable(cap: GLenum); procedure glDisable(cap: GLenum);
Для управления режимом сглаживания точек в качестве значения параметра должна быть указана константа GL_POINT_SMOOTH.
В библиотеке OpenTK для реализации этих команд используются статические методы класса GL (C#):
void Enable(EnableCap cap); void Disable(EnableCap cap);
Для управления режимом сглаживания необходимо указать значение PointSmooth перечисления EnableCap.
При отключенном режиме сглаживания точка рисуется в виде квадрата. При включенном режиме сглаживания библиотека пытается изобразить точку в виде круга. На рис 4.1 приведены изображения точки разных размеров с выключенным (изображения слева) и включенным (изображения справа) режимом сглаживания.
(рис 4.1) Изображения точки разного размера с использованием режима сглаживания и без него
Библиотека реализует три примитива для формирования отрезков.
Для формирования несвязанных отрезков значение параметра команды Begin должно быть равно значению Lines перечисления BeginMode при использовании библиотеки OpenTK (C#) и константе GL_LINES в программе на Object Pascal.
Каждая пара вершин определяет отрезок. Если задано нечетное количество вершин, то последняя вершина игнорируется и не будет использоваться для построения отрезков. Если будет задана всего одна вершина, то библиотека не сможет построить ни одного отрезка, так как для создания отрезка требуется как был приведен пример формирования несвязанных отрезков. В и формируется три несвязанных отрезка, хотя вершин задано ).
GL.Begin(BeginMode.Lines); GL.Vertex3(-0.5, -0.5, 0); GL.Vertex3(-0.5, 0.5, 0); GL.Vertex3(0, -0.5, 0); GL.Vertex3(0, 0.5, 0); GL.Vertex3(0.5, -0.5, 0); GL.Vertex3(0.5, 0.5, 0); GL.Vertex3(0.7, -0.5, 0); GL.End() |
glBegin(GL_LINES); glVertex3f(-0.5, -0.5, 0); glVertex3f(-0.5, 0.5, 0); glVertex3f(0, -0.5, 0); glVertex3f(0, 0.5, 0); glVertex3f(0.5, -0.5, 0); glVertex3f(0.5, 0.5, 0); glVertex3f(0.7, -0.5, 0); glEnd |
(рис 4.2) Схема формирования несвязанных отрезков
Для формирования ломаных линий значение параметра команды Begin должно быть равно значению LineStrip перечисления BeginMode при использовании библиотеки OpenTK (C#) и константе GL_LINE_STRIP в программе на языке Object Pascal.
При формировании этого примитива каждая вершина, начиная с третьей (первые две вершины используются для построения первого отрезка), будет соединяться отрезком с предыдущей вершиной. Т. е. каждая вершина, начиная со второй, используется для создания очередного отрезка.
Если в листинге 4.1 заменить параметр процедуры ).
(рис 4.3) Схема формирования ломаной линии
| (рис 4.4) Схема формирования замкнутой ломаной
|
|---|
Для формирования замкнутой ломаной необходимо задать значение параметра mode команды Begin:
GL_LINE_LOOP в программе на языке Object Pascal;LineLoop перечисления BeginMode в программе на языке C#.Примитив формируется аналогично ломаной линии с одним дополнением: отрезком так же соединяются первая и последняя вершина. Таким образом, в результате получается замкнутая ломаная.
Если в листинге 4.1 программы на C# заменить параметр метода ). По сравнению с рис 4.1" type="example">листинге 4.1 программы на C# заменить параметр метода ). По сравнению с Чтобы получить аналогичный результат в программе на Object Pascal, фрагмент которой приведен в листинге 4.2, необходимо заменить параметр процедуры glBegin на константу GL_LINE_LOOP.
Для всех типов отрезков могут быть заданы такие параметры как ширина и сглаживание линий.
Для установки ширины линии используется команда LineWidth. В качестве параметра команде передается ширина линии в пикселах. В библиотеке OpenTK команда LineWidth реализуется с помощью статического метода класса GL (C#):
void LineWidth(float width);
В Object Pascal команда реализуется с помощью процедуры:
procedure glLineWidth (width: GLfloat);
Библиотека OpenGL имеет ограничение на максимальную ширину линии. Это значение, как и для размера точки, зависит от конкретной реализации библиотеки OpenGL. Алгоритм измерения ширины линии зависит от установленного режима сглаживания линий. По умолчанию режим сглаживания линий отключён. В этом случае ширина линии вычисляется вдоль оси OX или оси OY проекции в зависимости от угла наклона линии. Если координаты концов отрезка на проекции (x1, y1) и (x2, y2), то ширина отрезка будет вычисляться вдоль оси OY если |y1 – y2| < |x1 – x2| и в направлении оси OX если |y1 – y2| > |x1 – x2|. Поэтому при отключенном режиме сглаживания (режим по умолчанию) визуальная ширина линии может меняться в зависимости от угла наклона проекции линии.
При включенном режиме сглаживания линий толщина отрезка измеряется перпендикулярно линии. Для включения и отключения режима сглаживания линий используются соответственно команды Enable и Disable со значением параметра GL_LINE_SMOOTH на Object Pascal и значением LineSmooth перечисления EnableCap на C#.
Многоугольник представляет собой замкнутую форму, поверхность которой может быть закрашена и границы которой определяются набором вершин, соединённых отрезками. Многоугольники являются основными компонентами, из которых формируются трехмерные закрашенные объекты. Библиотека позволяет формировать несколько типов многоугольников: треугольники, четырехугольники, многоугольники.
У всех многоугольников выделяют лицевую и обратную грани. Библиотека позволяет для каждой из граней задавать различные свойства, например, такие как: свойства материала, видимость, освещённость, режим отображения. По умолчанию лицевой гранью является та, которая получается при обходе вершин против часовой стрелки.
Библиотека реализует три примитива для рисования треугольников: несвязанные треугольники, треугольники с общей гранью, треугольники с общей вершиной.
Для задания этого примитива используется константа GL_TRIANGLES в Object Pascal и значение Triangles перечисления BeginMode в библиотеке OpenTK на C# в качестве значения параметра команды Begin. Для построения каждого очередного треугольника требуется три вершины. Если задано количество вершин не кратное трем, то последние вершины игнорируются и не используются для построения треугольника.
В (C#) и (Object Pascal) приведены примеры формирования двух треугольников, имеющих различные направления обхода вершин. Последняя седьмая вершина игнорируется, так как для построения третьего треугольника необходимо еще две вершины. На рис 4.3" type="example"/> (C#) и (Object Pascal) приведены примеры формирования двух треугольников, имеющих различные направления обхода вершин. Последняя седьмая вершина игнорируется, так как для построения третьего треугольника необходимо еще две вершины. На порядок обхода вершин каждого треугольника. Для первого треугольника (расположен слева на рис 4.5) порядок обхода совпадает с направлением часовой стрелки и видимая сторона треугольника считается обратной. Для второго треугольника (расположен справа на рис 4.5) порядок обхода соответствует направлению против часовой стрелки и видимая сторона треугольника является лицевой.
GL.Begin(BeginMode.Triangles); // треугольник 1 GL.Vertex3(-0.7, -0.7, 0); GL.Vertex3(-0.7, 0.7, 0); GL.Vertex3(-0.1, -0.7, 0); // треугольник 2 GL.Vertex3(0.0, 0.2, 0); GL.Vertex3(0.5, -0.5, 0); GL.Vertex3(0.7, 0.3, 0); // отдельная вершина игнорируется GL.Vertex3(0.9, -0.9, 0); GL.End() |
glBegin(GL_TRIANGLES); // треугольник 1 glVertex3f(-0.7, -0.7, 0); glVertex3f(-0.7, 0.7, 0); glVertex3f(-0.1, -0.7, 0); // треугольник 2 glVertex3f(0.0, 0.2, 0); glVertex3f(0.5, -0.5, 0); glVertex3f(0.7, 0.3, 0); // отдельная вершина игнорируется glVertex3f(0.9, -0.9, 0); glEnd; |
(рис 4.5) Схема формирования отдельных треугольников
Для задания этого примитива в качестве параметра команды Begin используется константа GL_TRIANGLE_STRIP в Object Pascal и значение TriangleStrip перечисления BeginMode в библиотеке OpenTK на C#. Первые три вершины определяют первый треугольник. Каждая следующая вершина создает очередной треугольник на основе последних двух вершин предыдущего треугольника и новой вершины.
На рис 4.6 приведен результат формирования треугольников для фрагментов программ из и , если в листинге 4.3 (фрагмент программы на C#) значение параметра метода GL.Begin заменить на BeginMode.TriangleStrip, а в листинге 4.4 (фрагмент программы на Object Pascal) значение параметра процедуры glBegin заменить на константу GL_TRIANGLE_STRIP.
(рис 4.6) Схема формирования треугольников с общей гранью
Обратите внимание, что для второго и последующих треугольников
Причиной такого порядка обхода вершин является применение этого примитива. Он обычно используется для формирования фрагмента поверхности сложной фигуры в виде "ленты". Для этого в программе обычно используются циклические конструкции, которые поочередно задают вершины на верхней и нижней стороне такой "ленты". В результате используемого порядка обхода вершин (рис 4.6) направление обхода вершин всех треугольников совпадает с направлением обхода первого треугольника.
Для формирования этого примитива значение параметра команды Begin при использовании библиотеки OpenTK должно быть равно значению TriangleFan перечисления BeginMode, в Object Pascal значение параметра должно быть равно константе GL_TRIANGLE_FAN.
Каждая следующая вершина создает очередной треугольник на основе первой вершины первого треугольника и последних двух вершин.
В и приведены фрагменты программы на C# с использованием библиотеки
GL.Begin(BeginMode.TriangleFan); GL.Vertex3(-0.5, -0.5, 0); GL.Vertex3(0, 0.8, 0); GL.Vertex3(0.5, 0.6, 0); GL.Vertex3(0.8, 0.1, 0); GL.Vertex3(0.7, -0.6, 0); GL.End(); |
glBegin(GL_TRIANGLE_FAN); glVertex3f(-0.5, -0.5, 0); glVertex3f(0, 0.8, 0); glVertex3f(0.5, 0.6, 0); glVertex3f(0.8, 0.1, 0); glVertex3f(0.7, -0.6, 0); glEnd; |
(рис 4.7) Схема формирования треугольников с общей вершиной
Библиотека OpenGL реализуется два примитива для рисования четырехугольников: несвязанные четырехугольники и четырехугольники с общей гранью.
Для формирования данного примитива с использованием библиотеки OpenTK на C# в качестве параметра метода Begin класса GL необходимо указать значение Quads перечисления BeginMode. В Object Pascal для этого необходимо процедуре glBegin в качестве параметра указать константу GL_QUADS.
Для формирования каждого очередного четырехугольника используются четыре вершины. Если задано меньше 4 вершин, то четырехугольник не формируется.
GL.Begin(BeginMode.Quads); // первый четырехугольник GL.Vertex3(-0.9, -0.6, 0); GL.Vertex3(-0.9, 0.6, 0); GL.Vertex3(-0.3, 0.6, 0); GL.Vertex3(-0.3, -0.6, 0); // второй четырехугольник GL.Vertex3(0.3, -0.6, 0); GL.Vertex3(0.3, 0.6, 0); GL.Vertex3(0.9, 0.6, 0); GL.Vertex3(0.9, -0.6, 0); GL.End(); |
glBegin(GL_QUADS); // первый четырехугольник glVertex3f(-0.9, -0.6, 0); glVertex3f(-0.9, 0.6, 0); glVertex3f(-0.3, 0.6, 0); glVertex3f(-0.3, -0.6, 0); // второй четырехугольник glVertex3f(0.3, -0.6, 0); glVertex3f(0.3, 0.6, 0); glVertex3f(0.9, 0.6, 0); glVertex3f(0.9, -0.6, 0); glEnd; |
(рис 4.8) Схема формирования несвязанных четырехугольников
В плоскости XY четырехугольники могут формироваться с помощью команды
Rect [d f I s][v].
В C# команда реализуется с помощью набора статических методов класса GL, например:
void Rect(double x1, double y1, double x2, double y2); void Rect(ref double v1, ref double v2);
В Object Pascal эта команда реализуется с помощью ряда процедур, таких как:
procedure glRectd (x1, y1, x2, y2: GLdouble); procedure glRectfv (v1, v2: PGLfloat);
Данный примитив задается на C# с помощью значения QuadStrip перечисления BeginMode и константы GL_QUAD_STRIP на Object Pascal, которые передаются в качестве параметра команде Begin.
Для построения первого четырехугольника требуется 4 вершины. Для формирования каждого последующего четырехугольника требуется задать очередные две вершины. Если вершин недостаточно для построения очередного четырехугольника, то они игнорируются.
GL.Begin(BeginMode.QuadStrip);
for (int i = 0; i <= 2; ++i)
{
GL.Vertex3(-0.9 + 0.8 * i, -0.6, 0);
GL.Vertex3(-0.9 + 0.8 * i, 0.6, 0);
}
GL.End();
|
glBegin(GL_QUAD_STRIP);
for I := 0 to 2 do
begin
glVertex3f(-0.9 + 0.8*i, -0.6, 0);
glVertex3f(-0.9 + 0.8*i, 0.6, 0);
end;
glEnd;
|
(рис 4.9) Схема формирования четырехугольников с общей гранью
3) к последней вершине (4) последнего четырехугольника, затем к последней новой вершине (6) и к предпоследней новой вершине (5). В результате направление обхода вершин всех четырёхугольников совпадает с направлением обхода вершин первого четырехугольника.
Данный примитив задается на Object Pascal с помощью константы GL_POLYGON и на C# - с помощью значения Polygon перечисления BeginMode, которые передаются в качестве значения параметра команде Begin.
Пример формирования многоугольника приведен в (C#) и (Object Pascal). На рис 4.11" type="example"/> (C#) и (Object Pascal). На
GL.Begin(BeginMode.Polygon);
GL.Vertex3(-0.9, -0.6, 0);
GL.Vertex3(-0.9, 0.6, 0);
GL.Vertex3(0, 0.6, 0.3);
GL.Vertex3(0.9, 0, 0);
GL.Vertex3(0, -0.6, -0.3);
GL.End();
glBegin(GL_POLYGON);
glVertex3f(-0.9, -0.6, 0);
glVertex3f(-0.9, 0.6, 0);
glVertex3f(0, 0.6, 0.3);
glVertex3f(0.9, 0, 0);
glVertex3f(0, -0.6, -0.3);
glEnd;
(рис 4.10) Схема формирования многоугольника
Библиотека OpenGL позволяет определять ряд параметров для всех типов многоугольников.
Библиотека OpenGL позволяет для многоугольников определять режим отображения лицевых и обратных граней. Для этого используется команда
PolygonMode (face, mode: GLenum);
В библиотеке OpenTK на C# команда реализуется с помощью статического метода класса GL:
void PolygonMode(MaterialFace face, PolygonMode mode);
В Object Pascal команда реализуется с помощью процедуры:
procedure glPolygonMode (face, mode: GLenum);
Первый параметр команды face определяет грани, для которых определяется режим отображения. Параметр может принимать
значения, перечисленные в таблица 4.1.
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Лицевые грани многоугольников | MaterialFace.Front | GL_FRONT |
| Обратные грани многоугольников | MaterialFace.Back | GL_BACK |
| Лицевые и обратные грани многоугольников | MaterialFace.FrontAndBack | GL_FRONT_AND_BACK |
Второй параметр ).
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Выбранная грань будет отображаться в виде точек | PolygonMode.Point | GL_POINT |
| Выбранная грань будет отображаться в виде отрезков, соединяющих вершины | PolygonMode.Line | GL_LINE |
| Выбранная грань будет закрашиваться | PolygonMode.Fill | GL_FILL |
По умолчанию для лицевых и обратных граней используется режим закрашивания поверхности (GL_FILL в Object Pascal, PolygonMode.Fill – на C#).
Различные режимы отображения сторон многоугольников часто используются при отладке программ, формирующих сложные объекты.
Режим отбора граней позволяет определить, какие из граней (лицевые, обратные) будут отображаться. Для включения и выключения режима используются команды Enable и Disable с параметром GL_CULL_FACE на Object Pascal и значением CullFace перечисления EnableCap на C#.
По умолчанию режим отбора граней отключен и отображаются лицевые и обратные грани. Для задания граней многоугольников, которые не должны отображаться используется команда:
CullFace (mode: GLenum);
В C# команда реализуется с помощью статического метода класса GL библиотеки OpenTK:
void CullFace(CullFaceMode mode);
В Object Pascal команда реализуется с помощью процедуры:
procedure glCullFace (mode: GLenum);
В качестве параметра ).
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Не будут отображаться только лицевые грани | MaterialFace.Front | GL_FRONT |
| Не будут отображаться только обратные грани | MaterialFace.Back | GL_BACK |
| Не будут отображаться и лицевые и обратные грани, т.е. многоугольник отображаться не будет | MaterialFace.FrontAndBack | GL_FRONT_AND_BACK |
Режим отбора граней позволяет в ряде случаев уменьшить время формирования изображения за счет отключения формирования граней, которые никогда не видимы.
В лекции рассмотрено формирование основных примитивов библиотеки OpenGL: точек, отрезков (несвязанные отрезки, ломанная, замкнутая ломаная), треугольников (отдельные треугольники, треугольники с общей гранью и с общей вершиной), четырёхугольников (несвязанные четырёхугольники и четырёхугольники с общей гранью), многоугольников. Рассмотрены возможности изменения основных свойств этих примитивов, а также изменение режима отбора граней и отображения многоугольников.
Задание: Постройте график функции $$y=z sin(x n)$$. Реализуйте возможность интерактивного изменения коэффициентов $$z$$ и $$n$$ с помощью клавиатуры.
Для построения графиков функций часто удобно использовать примитив "ломаная линия", в котором каждый следующий отрезок строится как продолжение предыдущего отрезка. В качестве основы для программы можно использовать приложение, созданное в .
Построение графика можно выполнить в обработчике события OnPaint формы на Object Pascal и события Paint компонента GLControl на C#. Код для построения графика функции можно расположить непосредственно после фрагмента кода, выполняющего построение осей координат. Для реализации также необходимо будет использовать глобальные переменные:
C#: double n = 1; double z = 1; Object Pascal: var n: double =1; z: double =1;
График функции может быть построен с помощью фрагмента, приведенного ниже:
C#:
GL.Color3(1f, 0, 0);
GL.Begin(BeginMode.LineStrip);
for (int i = -50; i <= 50; ++i)
{
double x = i * 0.1;
GL.Vertex2(x, Math.Sin(x*n)*z);
}
GL.End();
Object Pascal:
glColor3f(1, 0, 0);
glBegin (GL_LINE_STRIP);
for i:=-50 to 50 do
begin
x := i*0.1;
glVertex2f (x, Sin(x*n)*z);
end;
glEnd;
В этом фрагменте кода предполагается, что область видимости вдоль направления оси OX будет не менее 10 единиц. Изменить размер сцены можно в обработчике события изменения размеров формы в программе на Object Pascal и изменения размеров графического компонента GLControl на C#.
C#:
private void glControl1_Resize(object sender, EventArgs e)
{
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-6, 6, -6, 6, -6, 6);
GL.MatrixMode(MatrixMode.Modelview);
glControl1.Invalidate();
}
Object Pascal:
procedure TfrmMain.FormResize(Sender: TObject);
begin
glViewport(0, 0, ClientWidth, ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(-6, 6, -6, 6, -6, 6);
glMatrixMode(GL_MODELVIEW);
InvalidateRect(Handle, nil, False);
end;
Для уменьшения и увеличения значения переменной n можно использовать клавиши со стрелками влево и вправо. Уменьшение и увеличение значения параметра z можно реализовать с помощью клавиш со стрелками вниз и вверх.
C#:
private void glControl1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Insert: AngleX += AngleDl; break;
case Keys.Delete: AngleX -= AngleDl; break;
case Keys.Home: AngleY += AngleDl; break;
case Keys.End: AngleY -= AngleDl; break;
case Keys.Prior: AngleZ += AngleDl; break;
case Keys.Next: AngleZ -= AngleDl; break;
case Keys.Up: z += 0.1; break;
case Keys.Down: z -= 0.1; break;
case Keys.Left: n -= 0.1; break;
case Keys.Right: n += 0.1; break;
}
glControl1.Invalidate();
Text =
String.Format("График функции y = {0}*Sin(x*{1})", z, n);
}
Object Pascal:
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
If Key = VK_ESCAPE then Close;
case Key of
VK_INSERT: inc(AngleX, AngleDl);
VK_DELETE: dec(AngleX, AngleDl);
VK_HOME: inc(AngleY, AngleDl);
VK_END: dec(AngleY, AngleDl);
VK_PRIOR: inc(AngleZ, AngleDl);
VK_NEXT: dec(AngleZ, AngleDl);
VK_UP: z := z + 0.1;
VK_DOWN: z := z - 0.1;
VK_LEFT: n := n - 0.1;
VK_RIGHT: n := n + 0.1;
end;
InvalidateRect(Handle, nil, False);
Caption := 'График функции y = '+ FloatToStr(z) +' *Sin(x*'+FloatToStr(n)+')';
end;
Цель лекции: Научиться использовать основные примитивы OpenGL для формирования изображения.
Пример № 4.1 Пример демонстрирует формирование несвязанных отрезков.
Пример № 4.2 Пример демонстрирует формирование замкнутой ломаной.
Пример № 4.3 Пример демонстрирует формирование несвязанных треугольников.
Пример № 4.4 Пример демонстрирует формирование треугольников с общими гранями.
Пример № 4.5 Пример демонстрирует формирование треугольников с общей вершиной.
Пример № 4.6 Пример демонстрирует формирование несвязанных четырехугольников.
Пример № 4.7 Пример демонстрирует формирование четырехугольников с общими гранями.
Пример № 4.8 Пример демонстрирует формирование многоугольника.
Пример № 4.9 Пример демонстрирует построение графика функции y = z*Sin(x*n) с возможностью изменения коэффициентов n и z с помощью клавиатуры.
В OpenGL все изображения формируются из графических примитивов, основными из которых являются точки, отрезки, треугольники, четырехугольники, многоугольники. Базовым графическим примитивом для построения сложных объёмных изображений является треугольник. Такие примитивы как четырехугольники и многоугольники хотя и создаются с помощью отдельных команд, но формируются библиотекой OpenGL из набора треугольников. Необходимая детализация сложных изображений достигается за счет уменьшения размера примитивов, из которых строится изображение, и увеличения их количества.
Формирование примитива начинается с вызова команды Begin и передачи ей в качестве значения параметра mode целочисленной константы, которая определяет формируемый примитив:
Begin (mode: GLenum);
В Object Pascal для реализации команды Begin используется процедура
procedure glBegin (mode: GLenum);
Например, для формирования точек используется константа GL_POINTS, для формирования отрезков –константа GL_LINES.
В библиотеке OpenTK для реализации команды Begin используется статический метод класса GL (C#):
void Begin(BeginMode mode);
Формируемый примитив определяется с помощью элемента перечисления BeginMode. Для формирования точек используется значение этого перечисления Points, для формирования отрезков – значение Lines.
Формирование примитивов завершается с помощью команды End.
В Object Pascal эта команда реализуется с помощью процедуры:
procedure glEnd;
В библиотеке OpenTK для реализации команды End используется статический метод класса GL (C#):
void End();
Все примитивы состоят из набора вершин. Для задания расположения вершин в пространстве используются нормализованные координаты.
Координаты каждой вершины определяются с помощью команды OpenGL:
Vertex[2 3 4][s i f d]
Вызов этой команды должен выполняться межу вызовами команд Begin и End, иначе команда Vertex будет проигнорирована библиотекой.
Команда может иметь от 2 до 4 параметров. Если команда имеет три параметра, то ей передаются декартовые координаты вершин. В варианте команды с двумя параметрами они соответствуют декартовым координатам по оси OX и OY, координата по оси OZ принимается равной нулю.
В Object Pascal команда Vertex реализована набором процедур, объявление двух из них приведено ниже:
procedure glVertex2d (x,y: GLdouble); procedure glVertex3d (x,y, z: GLdouble);
В библиотеке OpenTK команда реализуется с помощью статических методов класса GL с различным числом параметров и типами данных. Объявление двух из них приведено ниже.
void Vertex2(double x, double y); void Vertex3(double x, double y, double z);
Необходимо обратить внимание на то, что для каждого вызова команды Begin должен быть соответствующий вызов команды End. Их можно сравнить с парой операторов begin и end языка Pascal, которые так же являются парными. Но в отличие от них для команд Begin и End компилятор не проверяет их парность, и эта задача ложится полностью на программиста. При несоблюдении парности вызовов команд Begin и End часто возникают довольно сложно выявляемые ошибки в формировании изображения.
Для формирования точек в качестве значения параметра mode команды Begin необходимо указать значение:
GL_POINTS в программе на Object Pascal;Points перечисления BeginMode в программе на C#.Перед формированием точек могут быть указаны их размер и определён режим сглаживания, который будет использоваться при их отображении. Эти параметры должны быть установлены перед вызовом команды Begin.
Размер точки может быть установлен с помощью команды PointSize. В Object Pascal команда реализуется с помощью процедуры:
procedure glPointSize (size: GLfloat);
В библиотеке OpenTK для этого используется статический метод класса GL (C#):
void PointSize(float size);
По умолчанию размер точки равен одному пикселу. Необходимо обратить внимание на то, что хотя координаты точки задаются в масштабе сцены, но размер точки задается в координатах устройства вывода изображения. Связано это с тем, что точки формируются на одном из последних этапов формирования изображения – на этапе растеризации.
Управление режимом сглаживания точки осуществляется с помощью команд Enable и Disable. Команда Enable включает режим сглаживания точек, команда Disable отключает его. По умолчанию режим сглаживания точек отключен.
В Object Pascal эти команды реализованы с помощью процедур:
procedure glEnable(cap: GLenum); procedure glDisable(cap: GLenum);
Для управления режимом сглаживания точек в качестве значения параметра должна быть указана константа GL_POINT_SMOOTH.
В библиотеке OpenTK для реализации этих команд используются статические методы класса GL (C#):
void Enable(EnableCap cap); void Disable(EnableCap cap);
Для управления режимом сглаживания необходимо указать значение PointSmooth перечисления EnableCap.
При отключенном режиме сглаживания точка рисуется в виде квадрата. При включенном режиме сглаживания библиотека пытается изобразить точку в виде круга. На рис 4.1 приведены изображения точки разных размеров с выключенным (изображения слева) и включенным (изображения справа) режимом сглаживания.
(рис 4.1) Изображения точки разного размера с использованием режима сглаживания и без него
Библиотека реализует три примитива для формирования отрезков.
Для формирования несвязанных отрезков значение параметра команды Begin должно быть равно значению Lines перечисления BeginMode при использовании библиотеки OpenTK (C#) и константе GL_LINES в программе на Object Pascal.
Каждая пара вершин определяет отрезок. Если задано нечетное количество вершин, то последняя вершина игнорируется и не будет использоваться для построения отрезков. Если будет задана всего одна вершина, то библиотека не сможет построить ни одного отрезка, так как для создания отрезка требуется как был приведен пример формирования несвязанных отрезков. В и формируется три несвязанных отрезка, хотя вершин задано ).
GL.Begin(BeginMode.Lines); GL.Vertex3(-0.5, -0.5, 0); GL.Vertex3(-0.5, 0.5, 0); GL.Vertex3(0, -0.5, 0); GL.Vertex3(0, 0.5, 0); GL.Vertex3(0.5, -0.5, 0); GL.Vertex3(0.5, 0.5, 0); GL.Vertex3(0.7, -0.5, 0); GL.End() |
glBegin(GL_LINES); glVertex3f(-0.5, -0.5, 0); glVertex3f(-0.5, 0.5, 0); glVertex3f(0, -0.5, 0); glVertex3f(0, 0.5, 0); glVertex3f(0.5, -0.5, 0); glVertex3f(0.5, 0.5, 0); glVertex3f(0.7, -0.5, 0); glEnd |
(рис 4.2) Схема формирования несвязанных отрезков
Для формирования ломаных линий значение параметра команды Begin должно быть равно значению LineStrip перечисления BeginMode при использовании библиотеки OpenTK (C#) и константе GL_LINE_STRIP в программе на языке Object Pascal.
При формировании этого примитива каждая вершина, начиная с третьей (первые две вершины используются для построения первого отрезка), будет соединяться отрезком с предыдущей вершиной. Т. е. каждая вершина, начиная со второй, используется для создания очередного отрезка.
Если в листинге 4.1 заменить параметр процедуры ).
(рис 4.3) Схема формирования ломаной линии
| (рис 4.4) Схема формирования замкнутой ломаной
|
|---|
Для формирования замкнутой ломаной необходимо задать значение параметра mode команды Begin:
GL_LINE_LOOP в программе на языке Object Pascal;LineLoop перечисления BeginMode в программе на языке C#.Примитив формируется аналогично ломаной линии с одним дополнением: отрезком так же соединяются первая и последняя вершина. Таким образом, в результате получается замкнутая ломаная.
Если в листинге 4.1 программы на C# заменить параметр метода ). По сравнению с рис 4.1" type="example">листинге 4.1 программы на C# заменить параметр метода ). По сравнению с Чтобы получить аналогичный результат в программе на Object Pascal, фрагмент которой приведен в листинге 4.2, необходимо заменить параметр процедуры glBegin на константу GL_LINE_LOOP.
Для всех типов отрезков могут быть заданы такие параметры как ширина и сглаживание линий.
Для установки ширины линии используется команда LineWidth. В качестве параметра команде передается ширина линии в пикселах. В библиотеке OpenTK команда LineWidth реализуется с помощью статического метода класса GL (C#):
void LineWidth(float width);
В Object Pascal команда реализуется с помощью процедуры:
procedure glLineWidth (width: GLfloat);
Библиотека OpenGL имеет ограничение на максимальную ширину линии. Это значение, как и для размера точки, зависит от конкретной реализации библиотеки OpenGL. Алгоритм измерения ширины линии зависит от установленного режима сглаживания линий. По умолчанию режим сглаживания линий отключён. В этом случае ширина линии вычисляется вдоль оси OX или оси OY проекции в зависимости от угла наклона линии. Если координаты концов отрезка на проекции (x1, y1) и (x2, y2), то ширина отрезка будет вычисляться вдоль оси OY если |y1 – y2| < |x1 – x2| и в направлении оси OX если |y1 – y2| > |x1 – x2|. Поэтому при отключенном режиме сглаживания (режим по умолчанию) визуальная ширина линии может меняться в зависимости от угла наклона проекции линии.
При включенном режиме сглаживания линий толщина отрезка измеряется перпендикулярно линии. Для включения и отключения режима сглаживания линий используются соответственно команды Enable и Disable со значением параметра GL_LINE_SMOOTH на Object Pascal и значением LineSmooth перечисления EnableCap на C#.
Многоугольник представляет собой замкнутую форму, поверхность которой может быть закрашена и границы которой определяются набором вершин, соединённых отрезками. Многоугольники являются основными компонентами, из которых формируются трехмерные закрашенные объекты. Библиотека позволяет формировать несколько типов многоугольников: треугольники, четырехугольники, многоугольники.
У всех многоугольников выделяют лицевую и обратную грани. Библиотека позволяет для каждой из граней задавать различные свойства, например, такие как: свойства материала, видимость, освещённость, режим отображения. По умолчанию лицевой гранью является та, которая получается при обходе вершин против часовой стрелки.
Библиотека реализует три примитива для рисования треугольников: несвязанные треугольники, треугольники с общей гранью, треугольники с общей вершиной.
Для задания этого примитива используется константа GL_TRIANGLES в Object Pascal и значение Triangles перечисления BeginMode в библиотеке OpenTK на C# в качестве значения параметра команды Begin. Для построения каждого очередного треугольника требуется три вершины. Если задано количество вершин не кратное трем, то последние вершины игнорируются и не используются для построения треугольника.
В (C#) и (Object Pascal) приведены примеры формирования двух треугольников, имеющих различные направления обхода вершин. Последняя седьмая вершина игнорируется, так как для построения третьего треугольника необходимо еще две вершины. На рис 4.3" type="example"/> (C#) и (Object Pascal) приведены примеры формирования двух треугольников, имеющих различные направления обхода вершин. Последняя седьмая вершина игнорируется, так как для построения третьего треугольника необходимо еще две вершины. На порядок обхода вершин каждого треугольника. Для первого треугольника (расположен слева на рис 4.5) порядок обхода совпадает с направлением часовой стрелки и видимая сторона треугольника считается обратной. Для второго треугольника (расположен справа на рис 4.5) порядок обхода соответствует направлению против часовой стрелки и видимая сторона треугольника является лицевой.
GL.Begin(BeginMode.Triangles); // треугольник 1 GL.Vertex3(-0.7, -0.7, 0); GL.Vertex3(-0.7, 0.7, 0); GL.Vertex3(-0.1, -0.7, 0); // треугольник 2 GL.Vertex3(0.0, 0.2, 0); GL.Vertex3(0.5, -0.5, 0); GL.Vertex3(0.7, 0.3, 0); // отдельная вершина игнорируется GL.Vertex3(0.9, -0.9, 0); GL.End() |
glBegin(GL_TRIANGLES); // треугольник 1 glVertex3f(-0.7, -0.7, 0); glVertex3f(-0.7, 0.7, 0); glVertex3f(-0.1, -0.7, 0); // треугольник 2 glVertex3f(0.0, 0.2, 0); glVertex3f(0.5, -0.5, 0); glVertex3f(0.7, 0.3, 0); // отдельная вершина игнорируется glVertex3f(0.9, -0.9, 0); glEnd; |
(рис 4.5) Схема формирования отдельных треугольников
Для задания этого примитива в качестве параметра команды Begin используется константа GL_TRIANGLE_STRIP в Object Pascal и значение TriangleStrip перечисления BeginMode в библиотеке OpenTK на C#. Первые три вершины определяют первый треугольник. Каждая следующая вершина создает очередной треугольник на основе последних двух вершин предыдущего треугольника и новой вершины.
На рис 4.6 приведен результат формирования треугольников для фрагментов программ из и , если в листинге 4.3 (фрагмент программы на C#) значение параметра метода GL.Begin заменить на BeginMode.TriangleStrip, а в листинге 4.4 (фрагмент программы на Object Pascal) значение параметра процедуры glBegin заменить на константу GL_TRIANGLE_STRIP.
(рис 4.6) Схема формирования треугольников с общей гранью
Обратите внимание, что для второго и последующих треугольников
Причиной такого порядка обхода вершин является применение этого примитива. Он обычно используется для формирования фрагмента поверхности сложной фигуры в виде "ленты". Для этого в программе обычно используются циклические конструкции, которые поочередно задают вершины на верхней и нижней стороне такой "ленты". В результате используемого порядка обхода вершин (рис 4.6) направление обхода вершин всех треугольников совпадает с направлением обхода первого треугольника.
Для формирования этого примитива значение параметра команды Begin при использовании библиотеки OpenTK должно быть равно значению TriangleFan перечисления BeginMode, в Object Pascal значение параметра должно быть равно константе GL_TRIANGLE_FAN.
Каждая следующая вершина создает очередной треугольник на основе первой вершины первого треугольника и последних двух вершин.
В и приведены фрагменты программы на C# с использованием библиотеки
GL.Begin(BeginMode.TriangleFan); GL.Vertex3(-0.5, -0.5, 0); GL.Vertex3(0, 0.8, 0); GL.Vertex3(0.5, 0.6, 0); GL.Vertex3(0.8, 0.1, 0); GL.Vertex3(0.7, -0.6, 0); GL.End(); |
glBegin(GL_TRIANGLE_FAN); glVertex3f(-0.5, -0.5, 0); glVertex3f(0, 0.8, 0); glVertex3f(0.5, 0.6, 0); glVertex3f(0.8, 0.1, 0); glVertex3f(0.7, -0.6, 0); glEnd; |
(рис 4.7) Схема формирования треугольников с общей вершиной
Библиотека OpenGL реализуется два примитива для рисования четырехугольников: несвязанные четырехугольники и четырехугольники с общей гранью.
Для формирования данного примитива с использованием библиотеки OpenTK на C# в качестве параметра метода Begin класса GL необходимо указать значение Quads перечисления BeginMode. В Object Pascal для этого необходимо процедуре glBegin в качестве параметра указать константу GL_QUADS.
Для формирования каждого очередного четырехугольника используются четыре вершины. Если задано меньше 4 вершин, то четырехугольник не формируется.
GL.Begin(BeginMode.Quads); // первый четырехугольник GL.Vertex3(-0.9, -0.6, 0); GL.Vertex3(-0.9, 0.6, 0); GL.Vertex3(-0.3, 0.6, 0); GL.Vertex3(-0.3, -0.6, 0); // второй четырехугольник GL.Vertex3(0.3, -0.6, 0); GL.Vertex3(0.3, 0.6, 0); GL.Vertex3(0.9, 0.6, 0); GL.Vertex3(0.9, -0.6, 0); GL.End(); |
glBegin(GL_QUADS); // первый четырехугольник glVertex3f(-0.9, -0.6, 0); glVertex3f(-0.9, 0.6, 0); glVertex3f(-0.3, 0.6, 0); glVertex3f(-0.3, -0.6, 0); // второй четырехугольник glVertex3f(0.3, -0.6, 0); glVertex3f(0.3, 0.6, 0); glVertex3f(0.9, 0.6, 0); glVertex3f(0.9, -0.6, 0); glEnd; |
(рис 4.8) Схема формирования несвязанных четырехугольников
В плоскости XY четырехугольники могут формироваться с помощью команды
Rect [d f I s][v].
В C# команда реализуется с помощью набора статических методов класса GL, например:
void Rect(double x1, double y1, double x2, double y2); void Rect(ref double v1, ref double v2);
В Object Pascal эта команда реализуется с помощью ряда процедур, таких как:
procedure glRectd (x1, y1, x2, y2: GLdouble); procedure glRectfv (v1, v2: PGLfloat);
Данный примитив задается на C# с помощью значения QuadStrip перечисления BeginMode и константы GL_QUAD_STRIP на Object Pascal, которые передаются в качестве параметра команде Begin.
Для построения первого четырехугольника требуется 4 вершины. Для формирования каждого последующего четырехугольника требуется задать очередные две вершины. Если вершин недостаточно для построения очередного четырехугольника, то они игнорируются.
GL.Begin(BeginMode.QuadStrip);
for (int i = 0; i <= 2; ++i)
{
GL.Vertex3(-0.9 + 0.8 * i, -0.6, 0);
GL.Vertex3(-0.9 + 0.8 * i, 0.6, 0);
}
GL.End();
|
glBegin(GL_QUAD_STRIP);
for I := 0 to 2 do
begin
glVertex3f(-0.9 + 0.8*i, -0.6, 0);
glVertex3f(-0.9 + 0.8*i, 0.6, 0);
end;
glEnd;
|
(рис 4.9) Схема формирования четырехугольников с общей гранью
3) к последней вершине (4) последнего четырехугольника, затем к последней новой вершине (6) и к предпоследней новой вершине (5). В результате направление обхода вершин всех четырёхугольников совпадает с направлением обхода вершин первого четырехугольника.
Данный примитив задается на Object Pascal с помощью константы GL_POLYGON и на C# - с помощью значения Polygon перечисления BeginMode, которые передаются в качестве значения параметра команде Begin.
Пример формирования многоугольника приведен в (C#) и (Object Pascal). На рис 4.11" type="example"/> (C#) и (Object Pascal). На Библиотека Библиотека В библиотеке В Object Pascal команда реализуется с помощью процедуры: Первый параметр команды
GL.Begin(BeginMode.Polygon);
GL.Vertex3(-0.9, -0.6, 0);
GL.Vertex3(-0.9, 0.6, 0);
GL.Vertex3(0, 0.6, 0.3);
GL.Vertex3(0.9, 0, 0);
GL.Vertex3(0, -0.6, -0.3);
GL.End();
glBegin(GL_POLYGON);
glVertex3f(-0.9, -0.6, 0);
glVertex3f(-0.9, 0.6, 0);
glVertex3f(0, 0.6, 0.3);
glVertex3f(0.9, 0, 0);
glVertex3f(0, -0.6, -0.3);
glEnd;
(рис 4.10) Схема формирования многоугольника
Параметры многоугольников
OpenGL позволяет определять ряд параметров для всех типов многоугольников.Режим отображения граней многоугольника
OpenGL позволяет для многоугольников определять режим отображения лицевых и обратных граней. Для этого используется командаPolygonMode (face, mode: GLenum);
OpenTK на C# команда реализуется с помощью статического метода класса GL:void PolygonMode(MaterialFace face, PolygonMode mode);
procedure glPolygonMode (face, mode: GLenum);
face определяет грани, для которых определяется режим отображения. Параметр может принимать
значения, перечисленные в таблица 4.1.
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Лицевые грани многоугольников | MaterialFace.Front | GL_FRONT |
| Обратные грани многоугольников | MaterialFace.Back | GL_BACK |
| Лицевые и обратные грани многоугольников | MaterialFace.FrontAndBack | GL_FRONT_AND_BACK |
Второй параметр ).
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Выбранная грань будет отображаться в виде точек | PolygonMode.Point | GL_POINT |
| Выбранная грань будет отображаться в виде отрезков, соединяющих вершины | PolygonMode.Line | GL_LINE |
| Выбранная грань будет закрашиваться | PolygonMode.Fill | GL_FILL |
По умолчанию для лицевых и обратных граней используется режим закрашивания поверхности (GL_FILL в Object Pascal, PolygonMode.Fill – на C#).
Различные режимы отображения сторон многоугольников часто используются при отладке программ, формирующих сложные объекты.
Режим отбора граней позволяет определить, какие из граней (лицевые, обратные) будут отображаться. Для включения и выключения режима используются команды Enable и Disable с параметром GL_CULL_FACE на Object Pascal и значением CullFace перечисления EnableCap на C#.
По умолчанию режим отбора граней отключен и отображаются лицевые и обратные грани. Для задания граней многоугольников, которые не должны отображаться используется команда:
CullFace (mode: GLenum);
В C# команда реализуется с помощью статического метода класса GL библиотеки OpenTK:
void CullFace(CullFaceMode mode);
В Object Pascal команда реализуется с помощью процедуры:
procedure glCullFace (mode: GLenum);
В качестве параметра ).
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Не будут отображаться только лицевые грани | MaterialFace.Front | GL_FRONT |
| Не будут отображаться только обратные грани | MaterialFace.Back | GL_BACK |
| Не будут отображаться и лицевые и обратные грани, т.е. многоугольник отображаться не будет | MaterialFace.FrontAndBack | GL_FRONT_AND_BACK |
Режим отбора граней позволяет в ряде случаев уменьшить время формирования изображения за счет отключения формирования граней, которые никогда не видимы.
В лекции рассмотрено формирование основных примитивов библиотеки OpenGL: точек, отрезков (несвязанные отрезки, ломанная, замкнутая ломаная), треугольников (отдельные треугольники, треугольники с общей гранью и с общей вершиной), четырёхугольников (несвязанные четырёхугольники и четырёхугольники с общей гранью), многоугольников. Рассмотрены возможности изменения основных свойств этих примитивов, а также изменение режима отбора граней и отображения многоугольников.
Задание: Постройте график функции $$y=z sin(x n)$$. Реализуйте возможность интерактивного изменения коэффициентов $$z$$ и $$n$$ с помощью клавиатуры.
Для построения графиков функций часто удобно использовать примитив "ломаная линия", в котором каждый следующий отрезок строится как продолжение предыдущего отрезка. В качестве основы для программы можно использовать приложение, созданное в .
Построение графика можно выполнить в обработчике события OnPaint формы на Object Pascal и события Paint компонента GLControl на C#. Код для построения графика функции можно расположить непосредственно после фрагмента кода, выполняющего построение осей координат. Для реализации также необходимо будет использовать глобальные переменные:
C#: double n = 1; double z = 1; Object Pascal: var n: double =1; z: double =1;
График функции может быть построен с помощью фрагмента, приведенного ниже:
C#:
GL.Color3(1f, 0, 0);
GL.Begin(BeginMode.LineStrip);
for (int i = -50; i <= 50; ++i)
{
double x = i * 0.1;
GL.Vertex2(x, Math.Sin(x*n)*z);
}
GL.End();
Object Pascal:
glColor3f(1, 0, 0);
glBegin (GL_LINE_STRIP);
for i:=-50 to 50 do
begin
x := i*0.1;
glVertex2f (x, Sin(x*n)*z);
end;
glEnd;
В этом фрагменте кода предполагается, что область видимости вдоль направления оси OX будет не менее 10 единиц. Изменить размер сцены можно в обработчике события изменения размеров формы в программе на Object Pascal и изменения размеров графического компонента GLControl на C#.
C#:
private void glControl1_Resize(object sender, EventArgs e)
{
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-6, 6, -6, 6, -6, 6);
GL.MatrixMode(MatrixMode.Modelview);
glControl1.Invalidate();
}
Object Pascal:
procedure TfrmMain.FormResize(Sender: TObject);
begin
glViewport(0, 0, ClientWidth, ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(-6, 6, -6, 6, -6, 6);
glMatrixMode(GL_MODELVIEW);
InvalidateRect(Handle, nil, False);
end;
Для уменьшения и увеличения значения переменной n можно использовать клавиши со стрелками влево и вправо. Уменьшение и увеличение значения параметра z можно реализовать с помощью клавиш со стрелками вниз и вверх.
C#:
private void glControl1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Insert: AngleX += AngleDl; break;
case Keys.Delete: AngleX -= AngleDl; break;
case Keys.Home: AngleY += AngleDl; break;
case Keys.End: AngleY -= AngleDl; break;
case Keys.Prior: AngleZ += AngleDl; break;
case Keys.Next: AngleZ -= AngleDl; break;
case Keys.Up: z += 0.1; break;
case Keys.Down: z -= 0.1; break;
case Keys.Left: n -= 0.1; break;
case Keys.Right: n += 0.1; break;
}
glControl1.Invalidate();
Text =
String.Format("График функции y = {0}*Sin(x*{1})", z, n);
}
Object Pascal:
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
If Key = VK_ESCAPE then Close;
case Key of
VK_INSERT: inc(AngleX, AngleDl);
VK_DELETE: dec(AngleX, AngleDl);
VK_HOME: inc(AngleY, AngleDl);
VK_END: dec(AngleY, AngleDl);
VK_PRIOR: inc(AngleZ, AngleDl);
VK_NEXT: dec(AngleZ, AngleDl);
VK_UP: z := z + 0.1;
VK_DOWN: z := z - 0.1;
VK_LEFT: n := n - 0.1;
VK_RIGHT: n := n + 0.1;
end;
InvalidateRect(Handle, nil, False);
Caption := 'График функции y = '+ FloatToStr(z) +' *Sin(x*'+FloatToStr(n)+')';
end;
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.