Урок Инициализация в Windows я начинаю это пособие непосредственного с кода, разбитого на секции, каждая из которых будет подробно комментироваться. Первое, что вы должны сделать это создать проект в Visual C++


Примечание: если вы хотите отключить все источники света в сцене, примените команду glDisable(GL_LIGHTING)



страница17/27
Дата17.11.2018
Размер7.85 Mb.
ТипУрок
1   ...   13   14   15   16   17   18   19   20   ...   27

Примечание: если вы хотите отключить все источники света в сцене, примените команду glDisable(GL_LIGHTING). Для отключения определенного источника света надо использовать команду glEnable(GL_LIGHT{0-7}). Эти команды позволяют нам контролировать освещение в целом, а также источники по отдельности. Еще раз запомните, пока не отработает команда glEnable(GL_LIGHTING), ничего вы на своей 3D-сцене не увидите.

 

  // Фоновое освещение для источника LIGHT0



  glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);

  // Рассеянное освещение для источника LIGHT0

  glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);

  // Положение источника LIGHT0

  glLightfv(GL_LIGHT0, GL_POSITION, LightPos);     

  // Включить Light0

  glEnable(GL_LIGHT0);           

  // Включить освещение

  glEnable(GL_LIGHTING);           

 

В первой строке мы создаем новый квадратичный объект. Затем мы говорим OpenGL о типе генерируемых нормалей для нашего квадратичного объекта - нормали сглаживания. Третья строка включает генерацию координат текстуры для квадратичного объекта. Без этих строк – второй и третьей закрашивание объекта будет плоским и невозможно будет наложить на него текстуру.



 

Четвертая и пятая строки говорят OpenGL использовать алгоритм сферического наложения (Sphere Mapping) для генерации координат для текстуры. Это дает нам доступ к сферической поверхности квадратичного объекта.

 

  q = gluNewQuadric();  // Создать квадратичный объект



  // тип генерируемых нормалей для него – «сглаженные»

  gluQuadricNormals(q, GL_SMOOTH);

  // Включить текстурные координаты для объекта

  gluQuadricTexture(q, GL_TRUE);

  // Настройка сферического наложения

  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);

  // Настройка отображения сферы

  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);

  return TRUE;  // Инициализация прошла успешно

}

 



Нижеприведенная функция рисует наш объект (в самом деле, неплохо смотрящийся пляжный мяч).

 

Устанавливаем цвет с максимальной интенсивностью белого и подключаем текстуру мяча (состоящую из последовательности красной, белой и синей полос).



 

После этого мы рисуем квадратичную сферу (Quadratic Sphere) с радиусом в 0.35f, 32 срезами (разбиениями вокруг оси Z) и 16 полосами (разбиениями вдоль оси Z) (вверх и вниз).

 

void DrawObject()  // Рисование мяча



{

  glColor3f(1.0f, 1.0f, 1.0f);// Цвет - белый

  glBindTexture(GL_TEXTURE_2D, texture[1]);// Выбор текстуры 2 (1)

  gluSphere(q, 0.35f, 32, 16);// Рисование первого мяча

 

Нарисовав первый мяч, выбираем новую текстуру (EnvRoll), устанавливаем значение прозрачности в 40% и разрешаем смешивание цветов, основанное на значении альфа (прозрачности). КомандыglEnable(GL_TEXTURE_GEN_S) и glEnable(GL_TEXTURE_GEN_T) разрешают сферическое наложение.



 

После всего этого мы перерисовываем сферу, отключаем сферическое наложение  и отключаем смешивание.

 

Конечный результат – это отражение, которое выглядит как блики на пляжном мяче. Так как мы включили сферическое наложение, текстура всегда повернута к зрителю, даже если мяч вращается. Поэтому мы применили смешивание, так что новая текстура не замещает старую (одна из форм мультитекстурирования).



 

  glBindTexture(GL_TEXTURE_2D, texture[2]);// Выбор текстуры 3 (2)

  glColor4f(1.0f, 1.0f, 1.0f, 0.4f);// Белый цвет с 40%-й прозрачностью

  glEnable(GL_BLEND);               // Включить смешивание

  // Режим смешивания

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);

  // Разрешить сферическое наложение

  glEnable(GL_TEXTURE_GEN_S);          

  // Разрешить сферическое наложение

  glEnable(GL_TEXTURE_GEN_T);     

  // Нарисовать новую сферу при помощи новой текстуры

  gluSphere(q, 0.35f, 32, 16);

  // Текстура будет смешена с созданной для эффекта мультитекстурирования (Отражение)

  glDisable(GL_TEXTURE_GEN_S);      // Запретить сферическое наложение

  glDisable(GL_TEXTURE_GEN_T);      // Запретить сферическое наложение

  glDisable(GL_BLEND);              // Запретить смешивание

}

 

Следующая функция рисует пол, над которым парит наш мяч. Мы выбираем текстуру пола (EnvWall), и рисуем один текстурированный прямоугольник, расположенный вдоль оси Z.



 

void DrawFloor()    // Рисование пола

{

  glBindTexture(GL_TEXTURE_2D, texture[0]);// текстура 1 (0)



  glBegin(GL_QUADS);           // Начало рисования

    glNormal3f(0.0, 1.0, 0.0); // «Верхняя» нормаль

    glTexCoord2f(0.0f, 1.0f);  // Нижняя левая сторона текстуры

    glVertex3f(-2.0, 0.0, 2.0);//Нижний левый угол пола

 

    glTexCoord2f(0.0f, 0.0f);  //Верхняя левая сторона текстуры



    glVertex3f(-2.0, 0.0,-2.0);//Верхний левый угол пола

     


    glTexCoord2f(1.0f, 0.0f);  //Верхняя правая сторона текстуры

    glVertex3f( 2.0, 0.0,-2.0);//Верхний правый угол пола

     

    glTexCoord2f(1.0f, 1.0f);  //Нижняя правая сторона текстуры



    glVertex3f( 2.0, 0.0, 2.0);//Нижний правый угол пола

  glEnd();                     // конец рисования

}

Теперь одна забавная вещь. Здесь мы скомбинируем все наши объекты и изображения для создания сцены с отражениями.



 

Начинаем мы с того, что очищаем экран (GL_COLOR_BUFFER_BIT) синим цветом (задан ранее в программе). Также очищаются буфер глубины (GL_DEPTH_BUFFER_BIT) и буфер шаблона (GL_STENCIL_BUFFER_BIT). Убедитесь в том, что вы включили команду очистки буфера шаблона, так как это новая команда для вас и ее легко пропустить. Важно отметить, что при очистке буфера шаблона мы заполняем его нулевыми значениями.

 

После очистки экрана и буферов мы определяем наше уравнение для плоскости отсечения. Плоскость отсечения нужна для отсечения отражаемого изображения.



 

Выражение eqr[]={0.0f,-1.0f, 0.0f, 0.0f} будет использовано, когда мы будем рисовать отраженное изображение. Как вы можете видеть, Y-компонента имеет отрицательное значение. Это значит, что мы увидим пиксели рисунка, если они появятся ниже пола, то есть с отрицательным значением по Y-оси. Любой другой графический вывод выше пола не будет отображаться, пока действует это уравнение.

 

Больше об отсечении будет позже… читайте дальше.



 

int DrawGLScene(GLvoid)// Рисование сцены

{

  // Очистка экрана, буфера глубины и буфера шаблона



  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  // Уравнение плоскости отсечения для отсечения отраженных объектов

  double eqr[] = {0.0f,-1.0f, 0.0f, 0.0f};     

 

Итак, мы очистили экран и определили плоскости отсечения. Теперь перейдем к изюминке нашего руководства!



 

Сначала сбросим матрицу модели. После чего все процессы рисования будут начинаться из центра экрана. Затем мы перемещаемся вниз на 0.6f единиц (для наклонной перспективы пола) и в экран на значение zoom. Для лучшего понимания, для чего мы перемещаемся вниз на 6.0f единиц, я приведу вам простой пример. Если вы смотрите на лист бумаги на уровне своих глаз, вы его едва видите – так он скорее похож на тонкую полоску. Если вы переместите лист немного вниз, он перестанет быть похожим на линию. Вы увидите большую площадь бумаги, так как ваши глаза будут обращены вниз на лист вместо прямого взгляда на его ребро.

 

  glLoadIdentity();// Сброс матрицы модели



  // Отдаление и подъем камеры над полом (на 0.6 единиц)

  glTranslatef(0.0f, -0.6f, zoom);       

 

Далее мы настроим маску цвета – новую вещь в этом руководстве. Маска представлена 4 значениями : красный, зеленый, синий и альфа-значение(прозрачность). По умолчанию все значения устанавливаются в GL_TRUE.



 

Если бы значение красной компоненты в команде glColorMask({red},{green},{blue},{alpha}) было установлено вGL_TRUE и в то же самое время все другие значения были равны 0 (GL_FALSE), единственный цвет, который бы мы увидели на экране, это красный. Соответственно, если бы ситуация была обратной (красная компонента равнаGL_FALSE, а все остальные равны GL_TRUE), то на экране мы бы увидели все цвета за исключением красного.

 

Нам не нужно что-либо выводить на экран в данный момент, поэтому установим все четыре значения в 0.



 

  glColorMask(0,0,0,0);    // Установить маску цвета

 

Именно сейчас пойдет речь об изюминке урока… Настроим буфер шаблона и проверку шаблона.



 

Сначала включается проверка шаблона. После того, как была включена проверка шаблона, мы можем изменять буфер шаблона.

 

Немного сложно объяснить работу команд, приводимых ниже, так что, пожалуйста, потерпите, а если у вас есть лучшее объяснение, пожалуйста, дайте мне знать. Строка glStencilFunc(GL_ALWAYS, 1, 1) сообщает OpenGL тип проверки, производимой для каждого пикселя выводимого на экран объекта (если пиксель не выводиться, то нет и проверки - прим.перев.).



 

Слово GL_ALWAYS говорит OpenGL, что тест работает все время. Второй параметр – это значение ссылки, которое мы проверяем в третьей строке, и третий параметр – это маска. Маска – это значение, поразрядно умножаемое операцией AND (логическое умножение из булевой алгебры – прим.перев.) на значение ссылки и сохраняемое в буфере шаблона в конце обработки. Значение маски равно 1, и значение ссылки тоже равно 1. Так что, если мы передадим OpenGL эти параметры, и тест пройдет успешно, то в буфере шаблона сохранится единица (так как 1(ссылка)&1(маска)=1).

 

Небольшое разъяснение: тест шаблона – это попиксельная проверка изображения объектов, выводимых на экран во время работы теста. Значение ссылки, обработанное операцией логического умножения AND на значение маски, сравнивается с текущим значением в буфере шаблона в соответствующем пикселе, также обработанным операцией AND на значение маски.



 

Третья строка проверяет три различных состояния, основываясь на функции проверки шаблона, которую мы решили использовать. Первые два параметра – GL_KEEP, а третий -GL_REPLACE.

 

Первый параметр говорит OpenGL что делать в случае если тест не прошел. Так как этот параметр у нас установлен в GL_KEEP, в случае неудачного завершения теста (что не может случится, так как у нас вид функции установлен вGL_ALWAYS), мы оставим состояние буфера в том виде, в котором оно было на это время.



 

Второй параметр сообщает OpenGL о том, что делать, если тест шаблона прошел успешно, а тест глубины – нет. Далее в программе мы так и так отключаем тест глубины, поэтому этот параметр может быть игнорирован.

 

И, наиболее важный, третий параметр. Он сообщает OpenGL о том, что надо делать в случае, если весь тест пройден успешно. В приведенном ниже участке программы мы говорим OpenGL, что надо заместить (GL_REPLACE) значение в буфере шаблона. Значение, которое мы помещаем в буфер шаблона, является результатом логического умножения (операция AND) нашего значения ссылки и маски, значение которой равно 1.



 

Следующее, что нам надо сделать после указания типа теста, это отключить тест глубины и перейти к рисованию пола.

 

А теперь расскажу обо всем этом попроще.



 

Мы указываем OpenGL, что не надо ничего не отображать на экране. Значит, во время рисования пола мы ничего не должны видеть на экране. При этом любая точка на экране в том месте, где должен нарисоваться наш объект (пол) будет проверена выбранным нами тестом шаблона. Сначала буфер шаблона пуст (нулевые значения). Нам требуется, чтобы в том, месте, где должен был бы появиться наш объект (пол), значение шаблона было равной единице. При этом нам незачем самим заботиться о проверке. В том месте, где пиксель должен был бы нарисоваться, буфер шаблона помечается единицей. Значение GL_ALWAYS это обеспечивает. Это также гарантируют значения ссылки и маски, установленные в 1. Во время данного процесса рисования на экран ничего не выводится, а функция шаблона проверяет каждый пиксель и устанавливает в нужном месте 1 вместо 0.

 

        // Использовать буфер шаблона для «пометки» пола



  glEnable(GL_STENCIL_TEST);

  // Всегда проходит, 1 битовая плоскость, маска = 1

  glStencilFunc(GL_ALWAYS, 1, 1); // 1, где рисуется хоть какой-нибудь полигон

  glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

  glDisable(GL_DEPTH_TEST);// Отключить проверку глубины

  DrawFloor();// Рисование пола (только в буфере шаблона)

 

Теперь у нас есть невидимая шаблонная маска пола. Пока действует проверка шаблона, пиксели будут появляться, только в тех местах, где в буфере шаблона будет установлена 1. И он у нас устанавливается в 1 в том месте, где выводился невидимый пол. Это значит, что мы увидим рисунок лишь в том месте, где невидимый пол установил 1 в буфер шаблона. Этот трюк заставляет появиться отражение лишь на полу и нигде более!



 

Итак, теперь мы уверены, что отражение мяча нарисуется только на полу. Значит, пора рисовать само отражение! Включаем проверку глубины и отображение всех трех составляющих цвета.

 

Взамен использования значения GL_ALWAYS в выборе шаблонной функции мы станем использовать значениеGL_EQUAL. Значение ссылки и маски оставим равными 1. Для всех операций с шаблоном установим все параметры вGL_KEEP. Проще говоря, теперь любой объект может быть отображен на экране (поскольку цветовая маска установлена в истину для каждого цвета). Во время работы проверки шаблона, выводимые пиксели будут отображаться лишь в том месте, где буфер шаблона установлен в 1 (значение ссылки AND значение маски (1&1) равно 1, что эквивалентно (GL_EQUAL) значению буфера шаблона AND значение маски, что также равно 1). Если в том месте, где рисуется пиксель, буфер шаблона не равен 1, пиксель не отобразится. Значение GL_KEEP запрещает модифицировать буфер шаблона вне зависимости от результата проверки шаблона.



 

  glEnable(GL_DEPTH_TEST); // Включить проверку глубины

  glColorMask(1,1,1,1); // Маска цвета = TRUE, TRUE, TRUE, TRUE

  glStencilFunc(GL_EQUAL, 1, 1); // Рисуем по шаблону (где шаблон=1)

  // (то есть в том месте, где был нарисован пол)

  // Не изменять буфер шаблона

  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

 

Теперь подключим плоскость отсечения для отражения. Эта плоскость задается массивом eqr, и разрешает рисовать только те объекты, которые выводятся в пространстве от центра экрана (где находится наш пол) и ниже. Это способ для того, чтобы не дать отражению мяча появиться выше центра пола. Будет некрасиво, если он это сделает. Если вы еще не поняли, что я имею ввиду, уберите первую строку в приведенном ниже коде и переместите клавишами исходный мяч (не отраженный) через пол.



 

После подключения плоскости отсечения plane0(обычно применяют от 0 до 5 плоскостей отсечения), мы определяем ее, передав параметры из массива eqr.

 

Сохраняем матрицу (относительно ее позиционируются все объекты на экране) и применяем командуglScalef(1.0f,-1.0f,1.0f) для поворота всех вещей сверху вниз (придавая отражению реальный вид). Негативное значение для Y-параметра в этой команде заставляет OpenGL рисовать все в положении с обратной координатой Y (то есть, «вниз головой» - прим.перев.). Это похоже на переворачивание картинки сверху вниз. Объект с положительным значением по оси Y появляется внизу экрана, а не вверху. Если вы поворачиваете объект к себе, он поворачивается от вас (словом, представьте себя Алисой – прим.перев.). Любая вещь будет перевернута, пока не будет восстановлена матрица или не отработает та же команда с положительным значением Y-параметра (1) (glScalef({x},1.0f,{z}).



 

  glEnable(GL_CLIP_PLANE0);// Включить плоскость отсечения для удаления

  // артефактов(когда объект пересекает пол)

  glClipPlane(GL_CLIP_PLANE0, eqr);// Уравнение для отраженных объектов

  glPushMatrix();  // Сохранить матрицу в стеке

  glScalef(1.0f, -1.0f, 1.0f);  // Перевернуть ось Y

 

Первая нижеприведенная строка перемещает наш источник света в позицию, заданную в массиве LightPos. Источник света должен освещать правую нижнюю часть отраженного мяча, имитируя почти реальный источник света. Позиция источника света также перевернута. При рисовании «настоящего» мяча (мяч над полом) свет освещает правую верхнюю часть экрана и создает блик на правой верхней стороне этого мяча. При рисовании отраженного мяча источник света будет расположен в правой нижней стороне экрана.



 

Затем мы перемещаемся вниз или вверх по оси Y на значение, определенное переменной height. Перемещение также переворачивается, так что если значение height =0.5f, позиция перемещения превратится в -5.0f. Мяч появится под полом вместо того, чтобы появиться над полом!

 

После перемещения нашего отраженного мяча, нам нужно повернуть его по осям X и Y на значения xrot и yrotсоответственно. Запомните, что любые вращения по оси X также переворачиваются. Так, если верхний мяч поворачивается к вам по оси X, то отраженный мяч поворачивается от вас.



 

После перемещения и вращения мяча нарисуем его функцией DrawObject(), и восстановим матрицу из стека матриц, для восстановления ее состояния на момент до рисования мяча. Восстановленная матрица прекратит отражения по оси Y.

 

Затем отключаем плоскость отсечения (plan0), так как нам больше не надо ограничивать рисование нижней половиной экрана, и отключаем шаблонную проверку, так что теперь мы можем рисовать не только в тех точках экрана, где должен быть пол.



 

Заметьте, что мы рисуем отраженный мяч раньше пола.

 

    // Настройка источника света Light0



    glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 

    glTranslatef(0.0f, height, 0.0f);// Перемещение объекта

    // Вращение локальной координатной системы по X-оси

    glRotatef(xrot, 1.0f, 0.0f, 0.0f);

    // Вращение локальной координатной системы по Y-оси

    glRotatef(yrot, 0.0f, 1.0f, 0.0f);   

    DrawObject();// Рисование мяча (для отражения)

  glPopMatrix();    // Восстановить матрицу

  glDisable(GL_CLIP_PLANE0);// Отключить плоскость отсечения

  // Отключение проверки шаблона

  glDisable(GL_STENCIL_TEST);

 

Начнем эту секцию с позиционирования источника света. Так как ось Y больше не перевернута, свет будет освещать верхнюю часть экрана, а не нижнюю.



Включаем смешивание цветов, отключаем освещение и устанавливаем компоненту прозрачности в 80% в командеglColor4f(1.0f,1.0f,1.0f,0.8f). Режим смешивания настраивается командой glBlendFunc(), и полупрозрачный пол рисуется поверх отраженного мяча.

 

Если бы мы сначала нарисовали пол, а затем – мяч (как нам подсказывает логика – прим.перев.), результат выглядел бы не очень хорошо. Нарисовав мяч, а затем – пол, вы увидите небольшой участок пола, смешанный с рисунком мяча. Когда я посмотрю в синее зеркало, я предположу, что отражение будет немного синим.



 

Нарисовав сначала пол, последующим отображением пола мы придадим отраженному изображению мяча легкую окраску пола.

 

  glLightfv(GL_LIGHT0, GL_POSITION, LightPos);// Положение источника



  // Включить смешивание (иначе не отразится мяч)

  glEnable(GL_BLEND);

  // В течение использования смешивания отключаем освещение

  glDisable(GL_LIGHTING);

  // Цвет белый, 80% прозрачности

  glColor4f(1.0f, 1.0f, 1.0f, 0.8f);

  // Смешивание, основанное на «Source Alpha And 1 Minus Dest Alpha»

  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  DrawFloor();// Нарисовать пол

 

Теперь нарисуем «настоящий» мяч (парящий над полом). При рисовании пола освещение было отключено, но теперь мы опять его включим.



 

Так как смешивание нам более не потребуется, мы его отключаем. Если мы этого не сделаем, изображение мяча смешается с изображением пола. Нам не нужно, чтобы мяч выглядел, как его отражение, поэтому мы и отключаем смешивание цветов.

 

Мы не будем отсекать «настоящий» мяч. Если мяч будет проходить через пол, мы должны видеть его выходящим из пола снизу. Если мы будем использовать отсечение, мяч снизу пола не появится. При возникновении необходимости запретить мячу появляться снизу пола вы можете применить значение плоскости отсечения, где будет указано положительное значение Y-координаты. При этом мяч будет виден, только когда он будет рисоваться в верхней части экрана, до той Y-координаты, которую вы укажете в выражении плоскости отсечения. В данном демонстрационном примере у нас нет необходимости этого делать, поэтому мяч будет виден по обе стороны пола.



 

Затем мы перемещаемся на позицию вывода, заданную в переменной heght. Только теперь ось Y не перевернута, поэтому мяч двигается в направлении, противоположном направлению движения отраженного мяча.

 

Мяч вращается, и, опять же, поскольку ось Y на данный момент не перевернута, мяч будет вращаться в направлении, обратном направлению вращения отраженного мяча. Если отраженный мяч вращается к вам, «реальный» мяч вращается от вас. Это дополняет иллюзию отражения.



 

После перемещения и поворота мы рисуем мяч.

 

  glEnable(GL_LIGHTING);// Включить освещение



  glDisable(GL_BLEND);  // Отключить смешивание

  glTranslatef(0.0f, height, 0.0f);// Перемещение мяча

  glRotatef(xrot, 1.0f, 0.0f, 0.0f);// Поворот по оси X

  glRotatef(yrot, 0.0f, 1.0f, 0.0f);// Поворот по оси Y

  DrawObject();         // Рисование объекта

 

Следующий код служит для поворота мяча по осям X и Y. Для поворота по оси X увеличивается переменная xrot на значение переменной xrotspeed. Для поворота по оси Y увеличивается переменная yrot на значение переменнойyrotspeed. Если xrotspeed имеет слишком большое позитивное или негативное значение, мяч будет крутиться быстрее, чем, если бы xrotspeed было близко к нулю. То же касается и yrotspeed. Чем больше yrotspeed, тем быстрее мяч крутится по оси Y.



 

Перед тем, как вернуть TRUE, выполняется команда glFlush(). Эта команда указывает OpenGL выполнить все команды, переданные ему в конвейер, что помогает предотвратить мерцание на медленных видеокартах.

 

  xrot += xrotspeed; // Обновить угол вращения по X



  yrot += yrotspeed; // Обновить угол вращения по Y

  glFlush();   // Сброс конвейера OpenGL

  return TRUE; // Нормальное завершение

}

 



Следующий код обрабатывает нажатия клавиш. Первые 4 строки проверяют нажатие вами 4 клавиш (для вращения мяча вправо, влево, вниз, вверх).

 

Следующие 2 строки проверяют нажатие вами клавиш ‘A’ или ‘Z’. Клавиша  ‘A’ предназначена для приближения сцены, клавиша  ‘Z’ – для отдаления.



 

Клавиши ‘PAGE UP’ и ’ PAGE UP’ предназначены для вертикального перемещения мяча.

 

void ProcessKeyboard()  // Обработка клавиатуры



{

  if (keys[VK_RIGHT])  yrotspeed += 0.08f;// Вправо

  if (keys[VK_LEFT])  yrotspeed -= 0.08f; // Влево

  if (keys[VK_DOWN])  xrotspeed += 0.08f; // Вверх

  if (keys[VK_UP])  xrotspeed -= 0.08f;   // Вниз

 

  if (keys['A'])    zoom +=0.05f; // Приближение



  if (keys['Z'])    zoom -=0.05f; // Отдаление

 

  if (keys[VK_PRIOR])  height +=0.03f; // Подъем



  if (keys[VK_NEXT])  height -=0.03f;  // Спуск

}

 



Функция 


Каталог: forum
forum -> Лечение гепатозов
forum -> Система ведения овцеводства в крестьянско-фермерских и личных хозяйствах населения
forum -> Yaesuft-857 (ft-897) – переходник для подключения cat интерфейса к микрофонному разъему трансивера
forum -> Васильев Владимир Юрьевич
forum -> tl-wr1043ND Беспроводной гигабитный маршрутизатор серии n copyright & trademarks
forum -> Цели и задачи Контакта rtf docx
forum -> Назовите не менее трех результатов революции 1905- 1907гг. Приведите не менее трех положений, отражающих значение революции для отечественной истории начала 20 века


Поделитесь с Вашими друзьями:
1   ...   13   14   15   16   17   18   19   20   ...   27


База данных защищена авторским правом ©vossta.ru 2019
обратиться к администрации

    Главная страница