2.9 Упражнение:" Игра Арканоид"
Напишите игру "Arconoid" - летающий шарик, снизу подставка, пользователь стрелками или мышкой управляет подставкой и отбивает шарик.
Исходный файл смотрите здесь. Исполняемый файл здесь.
2.10 Резюме
На этом эта глава книги закончена. Вы научились рисовать трехмерные объекты и делать интерактивную анимацию, используя эти объекты. Этого, в общем-то, достаточно для написания примитивных программ.
Chapter 3
Рисуем простые объекты
3.1 Общие положения
Точки, линии, треугольники,четырехугольники, многоугольники - простые объекты, из которых состоят любые сложные фигуры. Все они рисуются следующим образом:
glBegin(GLenum type); // указываем, что будем рисовать
glVertex[2 3 4][s i f d](...); // первая вершина
………..
// тут остальные вершины
glVertex[2 3 4][s i f d](...); // последняя вершина
glEnd(); // закончили рисовать примитив
Сначала вы говорите, что будете рисовать - glBegin с соответсвующим параметром. Возможные значения type см. ниже. Далее вы указываете вершины, определяющие объкты указанного типа. И наконец, вы вызваете glEnd, чтобы указать, что вы закончили рисовать объекты типа, указанного в glBegin.
3.2 Точки
\\
// рисуем точки
glPointSize(2);
glBegin(GL_POINTS);
glColor3d(1,0,0);
glVertex3d(-4.5,4,0); // первая точка
glColor3d(0,1,0);
glVertex3d(-4,4,0); // вторая точка
glColor3d(0,0,1); // третья
glVertex3d(-3.5,4,0);
glEnd();
glPointSize(5);
glBegin(GL_POINTS);
glColor3d(1,0,0);
glVertex3d(-2,4,0); // первая точка
glColor3d(0,1,0);
glVertex3d(-1,4,0); // вторая точка
glColor3d(0,0,1); // третье
glVertex3d(0,4,0);
glEnd();
glPointSize(10);
glEnable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
glColor3d(1,0,0);
glVertex3d(2,4,0); // первая точка
glColor3d(0,1,0);
glVertex3d(3,4,0); // вторая точка
glColor3d(0,0,1); // третья
glVertex3d(4,4,0);
glEnd();
glDisable(GL_POINT_SMOOTH);
Вы можете нарисовать столько точек, сколько вам нужно. Вызывая glVertex3d, вы устанавливает новую точку. Так же вы можете вызывать glColor3d внутри glBegin/glEnd. Размер точки устанавливается с помощью функции void glPointSize(GLfloat size). Режим сглаживания устанавливается вызовом функции glEnable() с параметром GL_POINT_SMOOTH. \\\\Отключается соответственно вызовом glDisable() c этим параметром. Последние функции - glPointSize и glEnable/glDisable надо вызывать вне glBegin/glEnd, иначе они будут проигнорированы. Функции glEnable/glDisable включают/выключают множество опций, но вы должны учитывать, что некоторые опции влекут за собой большие вычисления и, следовательно, изрядно затормаживают ваше приложение, поэтому без надобности не стоит их включать.
3.3 Линии
\\\\\\\\\\\\\\
glLineWidth(1); // ширину линии устанавливаем 1
glBegin(GL_LINES);
glColor3d(1,0,0); // красный цвет
glVertex3d(-4.5,3,0); // первая линия
glVertex3d(-3,3,0);
glColor3d(0,1,0); // зеленый
glVertex3d(-3,3.3,0); // вторая линия
glVertex3d(-4,3.4,0);
glEnd();
glLineWidth(3); // ширина 3
glBegin(GL_LINE_STRIP); // см. ниже
glColor3d(1,0,0);
glVertex3d(-2.7,3,0);
glVertex3d(-1,3,0);
glColor3d(0,1,0);
glVertex3d(-1.5,3.3,0);
glColor3d(0,0,1);
glVertex3d(-1,3.5,0);
glEnd();
glLineWidth(5);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_LINE_STIPPLE); // разрешаем рисовать прерывистую линию
glLineStipple(2,58360); // устанавливаем маску пояснения см. ниже
glBegin(GL_LINE_LOOP);
glColor3d(1,0,0);
glVertex3d(1,3,0);
glVertex3d(4,3,0);
glColor3d(0,1,0);
glVertex3d(3,2.7,0);
glColor3d(0,0,1);
glVertex3d(2.5,3.7,0);
glEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_LINE_STIPPLE);
glLineStipple устанавливает маску, при помощи которой будут рисоваться штриховые линии. Второй параметр задает саму маску. В двоичном виде это число выглядит так: 0000000011111111, т.е. всего 16 бит, старшие восемь установлены в ноль, значит тут линии не будет. Младшие установлены в единицу, тут будет рисоваться линия. Первый параметр определяет, сколько раз повторяется каждый бит. Скажем, если его установить равным 2, то накладываемая маска будет выглядить так: 00000000000000001111111111111111. Чтобы высчитать маску, я воспользовался калькулятором.Набрал в нем число в двоичной форме и перевел его в десятичную систему.
Также линии можно рисовать, передавая в glBegin GL_LINE_STRIP и GL_LINE_LOOP. В первом случае будет рисоваться ломаная, т.е. первая вершина соединяется со второй, вторая с третьей и так далее. GL_LINE_LOOP идентичен GL_LINE_STRIP, только последняя вершина будет соединена с первой.
3.4 Треугольники
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // см. ниже
glBegin(GL_TRIANGLES);
glColor3d(1,0,0); // рисуем треугольник
glVertex3d(-4,2,0);
glVertex3d(-3,2.9,0);
glVertex3d(-2,2,0);
glEnd();
glLineWidth(2);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //рисуем проволочные треугольники
glBegin(GL_TRIANGLE_STRIP); // обратите внимание на порядок вершин
glColor3d(0,1,0);
glVertex3d(1,2,0);
glVertex3d(0,2.9,0);
glVertex3d(-1,2,0);
glVertex3d(0,1.1,0);
glEnd();
glEnable(GL_LINE_STIPPLE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_TRIANGLE_FAN);
glColor3d(0,0,1);
glVertex3d(4,2,0);
glVertex3d(2.6,2.8,0);
glVertex3d(2,2,0);
glVertex3d(3,1.1,0);
glEnd();
glDisable(GL_LINE_STIPPLE);
glPolygonMode устанавливает опции для отрисовки многоугольника. Первый параметр может принимать значения - GL_FRONT, GL_BACK и GL_FRONT_AND_BACK. Второй параметр указывает, как будет рисоваться многоугольник. Он примает значения - GL_POINT(рисуются только точки), GL_LINE(рисуем линии) и GL_FILL(рисуем заполненный многоугольник). Первый параметр указывает: к лицевой, тыльной или же к обеим сторонам применяется опция, заданная вторым параметром. Треугольники можно рисовать, передав GL_TRIANGLES_STRIP или GL_TRIANGLES_FAN в glBegin. В первом случае первая, вторая и третья вершины задают первый треугольник. Вторая, третья и четвертая вершина - второй треугольник. Третья, четвертая и пятая вершина - третий треугольник и т.д. Вершины n, n+1 и n+2 определят n-ый треугольник. Во втором случае первая, вторая и третья вершина задают первый треугольник. Первая, третья и четвертая вершины задают второй треугольник и т.д. Вершины 1, n+1, n+2 определяют n-ый треугольник.
3.5 Четырехугольники и многоугольники
Четырехугольники рисуются вызовом функции glBegin с параметром GL_QUADS или GL_QUAD_STRIP. Для первого случая каждые четыре вершины определяют свой четырехугольник. Во втором случае рисуются связанные четырехугольники. Первая, вторая, третья и четвертая вершина определяют первый четырехугольник. Третья, четвертая, пятая и шестая вершина - второй четырехугольник и т.д. (2n-1), 2n, (2n+1) и (2n+2) вершины задают n-ый четырехугольник. Многоугольники задаются вызывом glBegin с параметром GL_POLYGON. Все вершины определяют один многоугольник. Для многоугольников можно задавать стили при помощи выше описанной функции glPolygonMode, толщину линии, толщину точек и цвет.
3.6 Уражнение:"Многогранники"
Изобразите точки, линии, треугольники, многоугольники в одном окне, как показано ниже.
Исходный файл смотрите здесь. Исполняемый файл здесь.
3.7 Уражнение:"Многогранники"
Реализуйте проволочные многогранники с помощью проволочных треугольников, многоугольников и линий.
3.8 Резюме
Ну вот, вы еще на один шаг продвинулись в изучение библиотеки OpenGL. Теперь вы имеете представление о том, как рисовать элементарные фигуры. Из примитивов вы можете составить фигуры любой сложности.
Chapter 4
Полезные мелочи
4.1 Построение поверхностей
Существует набор функций для посторения сфер, цилиндров и дисков. Эти функции представляют очень мощный контроль за построением трехмерных объектов. Непосредственно рисовать вы будете, используя следующие функции: gluSphere, gluCylinder, gluDisk и gluPartialDisk. В начале книги вы научились строить трехмерные объекты с помощью функций из библиотеки Auxilary Library. Функции aux[Solid/Wire]Sphere, aux[Solid/Wire]Cylinder и aux[Solid/Wire]Cone просто вызывают gluSphere и gluCylinder. Как я уже ранее говорил, в aux[Solid/Wire]Cylinder и aux[Solid/Wire]Cone фирмы Microsoft имеются баги. Здесь будет подробно рассмотрено построение сфер и цилиндров, так что потребность в aux[Solid/Wire]Cylinder и aux[Solid/Wire]Cone отпадет.
Первым параметром для gluSphere, gluCylinder, gluDisk является указатель на объект типа GLUquadricObj. Далее следуют параметры непосредственно создаваемой фигуры. Для сферы - это радиус; для цилиндра - радиус нижнего основания, радиус верхнего основания и высота; для диска - внутренний радиус, внешний радиус и для частичного диска - внутренний радиус, внешний радиус, угол, с которого начинать рисовать, длина дуги в градусах, которую рисовать. Последние два параметра у всех этих функций одинаковы. Это число разбиений вокруг оси Z и число разбиений вдоль оси Z. Как я уже говорил, все сложные объекты состоят из простых: точек, линий и многоугольников. Вы понимаете, что нарисовать/создать идеально гладкую сферу или цилиндр невозможно. Поэтому строится приближение из плоскостей. Для этого и нужно указать количество разбиений. Чем больше разбиение, тем лучше будет выглядеть ваша сфера. Однако, задавать здесть число с шестью нулями не стоит. Это лишено всякого смысла. Оптимальным, на мой взгляд, является число от 10 до 20. Чем больше объект, тем больше нужно разбиений. Число разбиений вдоль и поперек я выставляю одинаковыми. Сначала вы должны создать объект типа GLUquadricObj с помощью функции gluNewQuadric. Теперь устанавливаете свойства с помощью функции gluQuadricDrawStyle. Доступны стили: GLU_FILL - рисуется сплошной объект, \\\\GLU_LINE - проволочный объект, \\GLU_POINT - рисуются только точки. Рисуете то, что хотите. И не забудьте удалить созданный объект, воспользовавшись gluDeleteQuadric.
Настало время поэкспериментировать. Создайте очередное консольное приложение и отредактируйте функцию display следующим образом.
void CALLBACK display(void)
{
GLUquadricObj *quadObj;
quadObj = gluNewQuadric(); // создаем новый объект для создания сфер и цилиндров
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
glColor3d(1,0,0);
gluQuadricDrawStyle(quadObj, GLU_FILL); // устанавливаем стиль: сплошной
gluSphere(quadObj, 0.5, 10, 10); // рисуем сферу радиусом 0.5
glTranslated(-2,0,0); // сдвигаемся влево
glRotated(45, 1,0,0); // поворачиваем
glColor3d(0,1,0);
gluQuadricDrawStyle(quadObj, GLU_LINE); // устанавливаем
// стиль: проволочный
gluCylinder(quadObj, 0.5, 0.75, 1, 15, 15);
glPopMatrix();
gluDeleteQuadric(quadObj);
auxSwapBuffers();
}
4.2 Упражнение: "Сфера, цилиндр и диски".
Доработайте код, приведенный выше, чтобы в первой строке показывались три сферы. Цвет и стили(GLU_POINT, GLU_LINE и GLU_FILL) должны быть разными. В следующих трех строках должны быть цилиндры, диски и частичные диски.
Исходный файл смотрите здесь. Исполняемый файл здесь.
4.3 Интерполяция цветов
Когда вы создаете многоугольник, вы можете задать цвет для каждой его вершины. Если разрешено сглаживание цветов, то многоугольник будет переливаться. Поясню на примере. Режим сглаживания по умолчанию разрешен. Он переключается функцией glShadeModel с аргументами \\\\GL_FLAT и GL_SMOOTH. GL_FLAT запрещает сглаживание. На мой взгляд, сглаживание редко нужно. Вещь красивая, но бесполезная. Я в своих неучебных программах этот режим никогда не использовал. Поэтому советую его отключать, особенно, при программировании анимации,чтобы не затормаживать приложение. Создайте очередной проект. В функцию main добавьте
glShadeModel(GL\_SMOOTH);
Функцию display отредактируйте следующим образом:
void CALLBACK display(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glBegin(GL_TRIANGLES);
glColor3d(1,0,0);
glVertex2d(0,0);
glColor3d(0,1,0);
glVertex2d(0,3);
glColor3d(0,0,1);
glVertex2d(3,0);
glEnd();
auxSwapBuffers();
}
Исходный файл смотрите здесь. Исполняемый файл здесь
4.4 Прозрачность
С помощью четвертого компонента цвета можно получать различные эффекты наложения объктов друг на друга, наложения цветов и т.п. Здесь я расскажу о наиболее нужном и распрострененном эффекте - прозрачности объектов. Для того, чтобы разрешить обрабатывать четвертый компонент цвета вы должны вызвать функцию glEnable с аргументом \\\\GL_ALPHA_TEST. Для получения требуемого эффекта прозрачности нужно разрешить наложение цветов - glEnable(GL_BLEND). \\И установить алгоритм, по которуму будут смешиваться два цвета - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). Учтите, что эти режимы очень затормаживают вывод изображения, поэтому я не рекомендую устанавливать эти режимы глобально, для воспроизведения всех объектов. Выделите из ваших объектов те, которым требуется этот режим, включайте и отключайте его своевременно. Именно поэтому, эти тесты я разместил в функции display. Создайте новый проект с именем transperence и отредактируйте функцию display, как показано ниже.
void CALLBACK display(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4d(1,0,0, 1);
auxSolidSphere( 1 );
glColor4d(0,1,0, 0.6);
auxSolidCylinder(2,3);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
auxSwapBuffers();
}
В заключение, добавлю, что если вы поменяете местами создание цилиндра и сферы, то никакого эффекта прозрачности не увидите. Это не баг, а фича - так задумано. Секрет прост: вы должны сначала рисовать дальние объекты, а потом ближние. Связано это с тем, что выполняется тест глубины. Теперь смотрите, что получается. Если вы сначала рисуете сферу(она удалена), а потом цилиндр, то выполняется это следующим образом.
-
Создаем сферу.
-
Выполняется тест глубины успешно, т.к. цилиндра пока нет.
-
В буфере рисуется сфера.
-
Создаем цилиндр.
-
Выполняется тест глубины успешно, т.к. стенка цилиндра ближе, чем сфера.
-
В буфере рисуется цилиндр, он закрывает сферу с учетом прозрачности.
Теперь смотрим, что происходит, если сначала нарисовать цилиндр, потом сферу.
-
Создаем цилиндр.
-
Выполняется тест глубины успешно.
-
В буфере рисуется цилиндр.
-
Создаем сферу.
-
Вполняется тест глубины аварийно, т.к. сфера создается за цилиндром.
-
В буфере ничего не рисуется.
В последнем случае вы увидите один цилиндр.
Исходный файл смотрите здесь. Исполняемый файл здесь.
4.5 Упражнение: "Снег"
Ранее рассматривалось приложение "Снеговик". Анимацию создавать вы тоже уже научились. Добавьте косой снег, только сделайте снеговика прозрачным, чтобы снежинки как бы пролетали сквозь него.
4.6 Плоскости отсечения
Если вам требуется нарисовать сферу или любой другой объект урезанным, то плоскости отсечения это то, что вам надо. Плоскостей отсечения может быть шесть штук. По умолчанию они все запрещены. Разрешается плоскость отсечения командой glEnable(GL_CLIP_PLANE0). \\\\Ноль на конце GL_CLIP_PLANE означает нулевую плоскость; можно указать один, два, три и т.д. Сама плоскость устанавливается функцией glClipPlane. Первый аргумент этой функции - это плоскость, второй - это массив из четырех элементов, в котором хранятся коэффициенты уравнения плоскости. Для тех, кто не помнит уравнения плоскости в трехмерном пространстве, напоминаю: A*x+B*y+C*z+D = 0. Вот эти самые A,B,C,D и являются теми четырьмя коэффициентами. Создайте новый проект с именем ClipPlane и отредактируйте функцию display, как показано ниже.
void CALLBACK display(void)
{
GLdouble equation[4] = {-1,-0.25,0,2};
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE0, equation);
glColor3d(1,0,0);
auxSolidSphere( 3 );
glDisable(GL_CLIP_PLANE0);
auxSwapBuffers();
}
Исходный файл смотрите здесь. Исполняемый файл здесь.
4.7 Упражнение: "Три плоскости"
Добавьте еще две плоскости. Расположите их так, чтобы они отсекали двумерный угол [(p)/2].
4.8 Трафарет
Зачем это может понадобиться, я не очень представляю. Рисовать прерывистую линию вы уже умеете. Трафарет - это то же самое, только для многоугольников. Вы разрешаете тест трафарета командой glEnable(GL_POLYGON_STIPPLE). \\\\Аналогично, как и в случае с линиями, тут нужно загружать массив, который задает битовую маску. Размер трафарета строго оговорен - 32х32 пикселя. 32х32 равняется 1024. 1024 делим на восемь бит, получаем 128 байт, т.е., чтобы закодировать трафарет, нужен массив из 128-ми байт. Тут уже, как в случае с линиями, калькулятором не посчитаешь. Поэтому я написал утилиту - pcx_2bpp, которая конвертирует pcx-файл в формате два бита на пиксель в массив на языке Си. Запускается она так:
>pcx_2bpp filename.pcx >array.c
Знак "больше" означает перенаправление стандартного вывода в файл array.c. Эта утилита абсолютно переносима. Нарисовав в каком-нибудь графическом пакете рисунок в формате 32х32х2bpp, сохраните его и обработайте моей утилитой. Получите массив, который вставьте в свою программу. В фунции main добавьте следующий код:
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(array);
4.9 Упражнение: "Совершенствуем Arcanoid"
Не знаю, правильно ли сказал. Мне кажется, что уродуем, а не совершенствуем. В общем, наложите трафарет на подставку и шар. Когда увидите трафарет на шаре, то поймете, почему я сказал: "Уродуем".
Исходный файл смотрите здесь. Исполняемый файл здесь.
4.10 Туман
Еще одна мелочь, которую мы рассмотрим - это включение тумана. За основу возьмем нашего снеговика. Надо сказать, что ведет туман себя довольно странно. Если его цвет установить белым, то при увелечении плотности тумана снеговик становится полностью белым, причем даже те его места, которые изначально были черными, т.к. не освещались. Когда я установил цвет тумана темно-серым - (0.25, 0.25, 0.25), то при увелечении плотности не освещенные его части как им и положено оставались черными, а видимые теряли яркость. Я скорее охарактерезовал бы средство тумана, как средство для изменения яркости, потому как на реальный туман, это к сожалению, не похоже. Итак, создайте новый проект с именем fog, скопируйте snowman.c в fog.c. Для того чтобы включить туман и поэксперементировать с его влиянием на изображение мы добавим две функции, которые будут обрабатывать события от стрелок вверх\вниз на клавиатуре. Код этих функций выглядит так, включите его сразу после включения заголовочных файлов:
float density;
void CALLBACK Key_UP(void )
{
density+=(float)0.1;
glFogf(GL_FOG_DENSITY, density);
}
void CALLBACK Key_DOWN(void )
{
density-=(float)0.1;
glFogf(GL_FOG_DENSITY, density);
}
Я также ввел глобальную переменную density, в ней хранится плотность тумана. При нажатие стрелок вверх\вниз будет вызываться соответсвующая функция и будет изменено значение тумана. Снеговик у нас все время перерисовывается, поэтому при следующей отрисовке кадра значение тумана обновится. Теперь надо отредактировать функцию main, добавленный код выделен серым фоном:
void main()
{
float pos[4] = {3,3,3,1};
float dir[3] = {-1,-1,-1};
float fogcolor[4] = {0.25,0.25,0.25,1}; // цвет тумана
auxInitPosition( 50, 10, 400, 400);
auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE );
auxInitWindow( "Snowman" );
auxIdleFunc(display);
auxReshapeFunc(resize);
auxKeyFunc(AUX_UP, Key_UP); // устанавливаем обработчик
auxKeyFunc(AUX_DOWN, Key_DOWN); // стрелок вверх/вниз
glEnable(GL_FOG); // разрешаем туман
glGetFloatv(GL_FOG_DENSITY, &density); // получаем значение плотности
glFogfv(GL_FOG_COLOR, fogcolor); // устанавливаем цвет тумана
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
auxMainLoop(display);
}
Я полагаю здесь все ясно, прокомментирую тут только одну функцию:
glGetFloatv(GL_FOG_DENSITY, &density);
С помощ ью этой функции я получаю значение плотности тумана, установленное по умолчанию. Первый аргумент этой функции указывает OpenGL значение какого параметра мы хотим получить. Второй аргумент - это адрес в памяти куда будет записано значение данного параметра.
4.11 Логические операции
Логические операции позволяют вам складывать цвет фрагмента находящегося в буфере с цветом, который туда поступает. Этот режим разрешается и запрещается вызовом функций glEnable\glDisable с параметром GL_COLOR_LOGIC_OP. Правило, по которому будут складываться цвета задается функцией glLogicOp. У нее один параметр - одна из следующих констант определенных в файле gl.h.
/* LogicOp */
#define GL_CLEAR 0x1500
#define GL_AND 0x1501
#define GL_AND_REVERSE 0x1502
#define GL_COPY 0x1503
#define GL_AND_INVERTED 0x1504
#define GL_NOOP 0x1505
#define GL_XOR 0x1506
#define GL_OR 0x1507
#define GL_NOR 0x1508
#define GL_EQUIV 0x1509
#define GL_INVERT 0x150A
#define GL_OR_REVERSE 0x150B
#define GL_COPY_INVERTED 0x150C
#define GL_OR_INVERTED 0x150D
#define GL_NAND 0x150E
#define GL_SET 0x150F
Мне не удалось найти разумного применения этой функции поэтому я приведу здесь лишь текст моей программы с комментариями, которая позволяет перебрать и посмотреть действие всех логических операций. Как и в предыдущем пункте у меня определена глобальная переменная и две функции реагирующие на нажатие стрелок на клавеатуре.
/*
* (c) Copyright 1995-2000, Igor Tarasov
* FidoNet: 2:5020/370.2 620.20 1103.5
* email: igor@itsoft.miem.edu.ru itarasov@rtuis.miem.edu.ru
* Phone: (095)916-89-51 916-89-63
*/
#include
#include
#include
#include
int logicop = GL_CLEAR;
void CALLBACK Key_UP(void )
{
if(logicop
logicop++;
}
void CALLBACK Key_DOWN(void )
{
if(logicop>GL_CLEAR)
logicop--;
}
void CALLBACK resize(int width,int height)
{
glViewport(0,0,width,height);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-5,5, -5,5, 2,12);
gluLookAt( 0,0,5, 0,0,0, 0,1,0 );
glMatrixMode( GL_MODELVIEW );
}
void CALLBACK display(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor4d(1,0,0, 1);
auxSolidSphere( 1 );
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(logicop);
glColor4d(0,1,0, 0.7);
auxSolidCylinder(2,3);
glDisable(GL_COLOR_LOGIC_OP);
auxSwapBuffers();
}
void main()
{
float pos[4] = {3,3,3,1};
float dir[3] = {-1,-1,-1};
GLfloat mat_specular[] = { 1,1,1,1};
auxInitPosition( 50, 10, 400, 400);
auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE );
auxInitWindow( "Glaux Template" );
auxIdleFunc(display);
auxReshapeFunc(resize);
auxKeyFunc(AUX_UP, Key_UP);
auxKeyFunc(AUX_DOWN, Key_DOWN);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
// glLightfv(GL_LIGHT0, GL_POSITION, pos);
// glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, 128);
auxMainLoop(display);
}
Достарыңызбен бөлісу: |