Chapter 7
Инициализация или как написать приложение с нуля

7.2  Консольное приложение - Win32 Console Application

     Достоинством приложений данного типа является переносимость на другие платформы при условии, что вы не пользовались другими платформенно зависимыми библиотеками. Реализация OpenGL Auxilary Library существует для большинства платформ. Также здесь значительно упрощена начальная инициализация, т.е. вы быстро можете начать программировать. Идеально подходит для начинающих. Именно поэтому, все примеры в этой книге я привязал к этому варианту приложения OpenGL. Хотя вы можете вставлять приводимый код в WinAPI-приложение и MFC-приложение, и все будет работать точно так же. Для Java-приложения вам придется добавить префиксы к функциям. Недостатком является урезанная функциональность. Вы не можете обрабатывать все сообщения, которые приходят вашему окну. Такой тип приложения идеально подходит для написания небольших портабельных утилит, размером до 25Kb.
     Здесь, как я уже говорил, начальная инициализация самая простая. Библиотека сделает за вас большинство действий. От вас потребуется совсем немного по сравнению с другими типами приложений. Итак, давайте для начала создадим проект. Общепризнанно, что тремя наилучшими компиляторами считаются GNU C, Microsoft C и Watcom C. Inprise(Borland) отпадает. Компиляторами других фирм я не пользовался. Все мои задачи решались вышеуказанными четырьмя компиляторами. Правда, должен заметить, что с 1997 года я практически прекратил пользоваться компилятором фирмы Borland. Лишь изредка, когда нужно было перекомпилировать старые утилиты, написанные еще для MSDOS. Эта книга для начинающих, и я хочу сделать ее понятной большинству читателей. Поэтому я не буду рассматривать проекты для GNU C или Watcom C. Не хочу здесь городить непонятные многим начинающим makefile'ы. Однако, в конце данной главы будет разобрано приложение для UNIX, там уже от makefile'ов никуда не деться. Теперь вернемся к нашим баранам:

  1. Запустите MSVisualC++6.0
  2. Щелкните меню File->New->Win32 Console Application.
  3. Выберете каталог и имя проекта задайте glaux, щелкните OK.
  4. Выберете An Empty Project, щелкните Finish.
  5. Создайте новый текстовый файл и сохраните его с именем glaux.c.
  6. Присоедините его к проекту. Project->Add To Project->Files
  7. Щелкните Build->Set Active Configuration и установите тип проекта glaux - Win32 Release
  8. Далее щелкаете Project->Settings->Link->Object/library modules: и добавьте туда opengl32.lib, glu32.lib и glaux.lib

     Проект у нас теперь есть, давайте писать glaux.c. Файл, в котором находится исходный код программы, желательно начинать с комментария. Это необязательно, но этого требует хороший стиль. В комментариях можно указать имя автора, способ связи - обычно, адрес электронной почты. Далее, можно кратко описать, что находится в этом файле. Неплохо вести некоторый дневник здесь же: что и когда вы добавили. У меня эти комментарии выглядят так:

/*
 * (c) Copyright 1995-1999, Igor Tarasov
 * FidoNet: 2:5020/370.2 620.20 1103.5
 * Inet: itarasov@rtuis.miem.edu.ru
 * Phone: (095)916-89-51 916-89-63
 */

Теперь надо включить заголовочные файлы:

#include <windows.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

Давайте напишем функцию main(). Я посчитал, что наиболее правильно и понятно будет дать код и прокомментировать его подробно. У меня функция main() выглядит так:

void main()
{
        float pos[4] = {3,3,3,1};
        float dir[3] = {-1,-1,-1};

    // указываем координаты окна на экране
    // верхний левый угол (50,10)
    // ширина и высота - 400
    auxInitPosition( 50, 10, 400, 400);

    // устанавливаем параметры контекста OpenGL
    //
    auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE );

    // создаем окно на экране
    auxInitWindow( "Glaux Template" );

    // наше окно будет получать сообщения
    // от клавиатуры, мыши, таймера или любые другие
    // когда никаких сообщений нет
    // будет вызываться функция display
    // так мы получаем анимацию
    // если вам нужна статическая картинка,
    // то закомментируйте следующую строку
    auxIdleFunc(display);

    // при изменении размеров окна
    // придет соответсвующее сообщение
    // в Windows - это WM_SIZE
    // мы устанавливаем функцию resize,
    // которая будет вызвана
    // при изменении размеров окна
    auxReshapeFunc(resize);


    // далее, я устанавливаю ряд тестов и параметров

    // тест прозрачности, т.е. будет учитываться
    // четвертый параметр в glColor
    glEnable(GL_ALPHA_TEST);

    // тест глубины
    glEnable(GL_DEPTH_TEST);

    // glColor будет устанавливать
    // свойства материала
    // вам не надо дополнительно
    // вызывать glMaterialfv
    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);

   // и последнее, устанавливаем
   // функцию display отрисовки окна
   // эта функция будет вызываться всякий раз,
   // когда потребуется перерисовать окно
   // например, когда вы развернете окно на весь экран


   // в windows - это обработчик сообщения WM_PAINT
    auxMainLoop(display);
}

Вот и все с функцией main(). Осталось написать код функции resize и функции display. Вставьте следующий код перед функцией main().

void CALLBACK resize(int width,int height)
{

   // Здесь вы указываете ту чать окна,
   // куда осуществляется вывод OpenGL.
   glViewport(0,0,width,height);


   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();

   // Устанавливаем тип проекции.
   // glOrtho - параллельная
   // glFrustum - перспективная
   // Параметры у этих функций одинаковые.
   // Они определяют объем, который вы видите.
   // левая стенка - пять единиц влево
   // правая - пять единиц вправо
   // далее, нижняя стенка и верхняя
   // и наконец, передняя и задняя
   // см. ниже картинку
   glOrtho(-5,5, -5,5, 2,12);

   // Устанавливаем точку, в которой
   // находится наш глаз ---(0,0,5)
   // направление, куда смотрим --- (0,0,0)
   // вектор, принимаемый за направление вверх --- (0,1,0)
   // этим вектором является ось Y
   gluLookAt( 0,0,5, 0,0,0, 0,1,0 );

   glMatrixMode( GL_MODELVIEW );
}

     Здесь нужно сделать пояснения по поводу glMatrixMode. Функции glOrtho и glFrustum работают с матрицей, отвечающей за тип проекции. Они просто загружают соответствующую матрицу. Вы можете установить свой тип проекции, если вам это понадобится. Сначала вы говорите, что будете изменять матрицу проекции - glMatrixMode с параметром GL_PROJECTION. Потом, с помощью glLoadMatrix загружаете соответсвующую матрицу. Функции glTranslate/glRotate работают с матрицей вида. Ее мы загружаем последней строкой - glMatrixMode( GL_MODELVIEW ).
     В параметрах контекста воспроизведения мы установили AUX_DOUBLE. Это значит, что рисоваться все будет сначала в буфер. Для того, что бы скопировать содержимое буфера на экран, вызывается функция auxSwapBuffers(). Если вы программировали анимацию для MSDOS или Windows, то наверняка использовали такой прием, чтобы избавиться от мерцания на экране. В функции display мы сначала очищаем буфер. Цвет, которым заполняется буфер при очищении, можно установить в функции main() вызовом glClearColor(r,g,b).

void CALLBACK display(void)
{
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        /* remove next tree lines
         * and enter your code here
         */
        glTranslated(0.01,0,0);
            glColor3d(1,0,0);
        auxSolidSphere( 1 );


  auxSwapBuffers();

}

Вот и все.


Исходный файл смотрите здесь. Исполняемый файл здесь.