Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 20:

Геометрические примитивы в OpenGL

Ломаные и замкнутые линии

Последовательность ломаных линий, соединяющих точки в порядке их определения на сцене оператором glVertex3f задается в команде glBegin флагом GL_LINE_STRIP. Если нужно соединить точки и замкнуть контур, применяется опция GL_LINE_LOOP (петля). Это можно легко проверить, заменив соответствующий флаг в функции Points() файла Points.h нашего тестового проекта Primitives. Результат будет таким



Такие схемы рисования удобно применять для аппроксимации кривых линий ломаными отрезками прямых (например, при построении графиков, заданных наборами чисел).

Упражнение 4. Управление шириной линий (LinesW)

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

void glLineWidth(GLfloat width);

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

GLfloat sizes[2], step;
glGetFloatv(GL_POINT_WIDTH_RANGE, sizes);  // Получаем диапазон
glGetFloatv(GL_POINT_WIDTH_GRANULARITY, &step);  // Получаем шаг

Массив размеров содержит наименьший и наибольший возможные значения ширины линий, поддерживаемый функцией glLineWidth(). При приближении ширины линии к краю диапазона изменение ширины замораживается.

Проверим сказанное на практике.

  • В панели Solution Explorer двойным щелчком левой кнопкой мыши на файле PointsZ.h откройте его на редактирование.
  • Выполните команду File/Save PointsZ.h As меню оболочки и запишите в текущий каталог проекта копию файла с именем LinesW.h

  • В панели Solution Explorer вызовите контекстное меню для узла Primitives проекта и командой Add/Existing Item присоедините файл LinesW.h к текущему проекту
  • Очистите содержимое вновь полученного файла и замените его следующим кодом
//**********************************************************
// Функция рисования линий с увеличением ширины
void LinesW() 
{
  // Запомнить первоначальное состояние матрицы вращения
  glPushMatrix();
  
  // Настроить два последовательных поворота
  // для будущей визуализации сцены
  glRotatef(xRot, 1.0f, 0.0f, 0.0f);// Первое состояние матрицы вращения
  glRotatef(yRot, 0.0f, 1.0f, 0.0f);// Следующее состояние
  
  GLfloat sizes[2], step; // Для определения диапазона и 
              // шага изменения ширины линий
  glGetFloatv(GL_LINE_WIDTH_RANGE, sizes);// Получаем диапазон
  GLfloat curSize = sizes[0]; // Сначала установим минимальный размер
  glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &);  // Получаем шаг
  
  GLfloat y; // Переменная для координаты y
  
  // Пошаговый проход по оси y с шагом 20 единиц снизу вверх
  // Получится 10 линий по размеру отсекающего куба в плоскости z = 0
  for(y = -90.0f; y <= 90.0f; y += 20.0f){
    // Задаем ширину линии
    glLineWidth(curSize);
  
    // Посылаем на визуализацию каждую линию по отдельности
    glBegin(GL_LINES);
      // Задаем два конца линии в плоскости z = 0
      glVertex2f(-90.0f, y);
      glVertex2f(90.0f, y);
    glEnd(); // Закончили визуализацию
  
    curSize += 3.0f * step;  // Увеличиваем ширину линии 
                // с помощью весового коэффициента
  }
  
  // Восстанавливаем матрицу вращения в исходное состояние
  glPopMatrix();
    
  // Восстанавливаем минимальный размер ширины
  glLineWidth(sizes[0]);
}
Листинг 21.23. Код файла LinesW.h управления шириной линий

Обратите внимание, что для разнообразия мы использовали glVertex2f вместо glVertex3f, поскольку мы рисуем все линии на плоскости x0y при значении координаты z равной нулю. Клавиши со стрелками в нынешнем варианте все еще продолжают функционировать.

  • Разместите в конце файла Primitives.cpp включение файла LinesW.h
.................................................  
#include "Points.h"  // Включение перенесенного кода
#include "PointsZ.h"  // Включение кода рисования точек с увеличением размера
#include "Lines.h"    // Веер линий  
#include "LinesW.h"  // Проверяется изменение ширины линий
.................................................
Листинг 21.24. Конец файла Primitives.cpp
  • Добавьте в начало файла Primitives.cpp прототип функции LinesW()
.................................................  
// Прототипы функций
void RenderScene(void);
void SetupRC(void);
void ExecuteMenu(int);
void ChangeSize(int, int);
void Points(); // Пустой аргумент необязателен
void SpecialKeys(int key, int x, int y);// Можно указать только типы
void PointsZ();
void Lines();  
void LinesW();  
.................................................
Листинг 21.25. Добавление прототипа функции LinesW() в начало файла Primitives.cpp
  • Скорректируйте меню в функции main() файла Primitives.cpp
.................................................  
  // Создание меню и добавление опций выбора
  glutCreateMenu(ExecuteMenu);
  glutAddMenuEntry("Рисование функцией Points", 1);
  glutAddMenuEntry("Точки с увеличением размера", 2);
  glutAddMenuEntry("Веер линий", 3);
  glutAddMenuEntry("Управление шириной линий", 4);
  glutAttachMenu(GLUT_RIGHT_BUTTON);// Присоединяем 
  // Конец создания меню
.................................................
Листинг 21.26. Корректировка меню в файле Primitives.cpp
  • Скорректируйте обработку выбора пользователя в функции рендеринга файла Primitives.cpp
//****************************************************
// Функция обратного вызова для рисования сцены
void RenderScene(void)
{
  // Окно очищается текущим цветом,
  // установленным функцией glClearColor()
  glClear(GL_COLOR_BUFFER_BIT);
  
  // Отработка выбора пользователя
  switch(::choice){
    case 1:
      Points();
      break;
    case 2:
      PointsZ();
      break;
    case 3:
      Lines();
      break;
    case 4:
      LinesW();
      break;
  }
  
  // Исполнить (очистить) очередь команд
  glFlush();}
Листинг 21.27. Корректировка функции RenderScene() в файле Primitives.cpp
  • Запустите приложение и получите следующий результат при управлении стрелками


Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000