КГ_8глава (Компьютерная графика)
Описание файла
Файл "КГ_8глава" внутри архива находится в папке "Компьютерная графика". Документ из архива "Компьютерная графика", который расположен в категории "". Всё это находится в предмете "инженерная графика" из 4 семестр, которые можно найти в файловом архиве РТУ МИРЭА. Не смотря на прямую связь этого архива с РТУ МИРЭА, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "компьютерная графика" в общих файлах.
Онлайн просмотр документа "КГ_8глава"
Текст из документа "КГ_8глава"
Примеры использования классов языка C++
Рассмотрим пример графической программы, создающей изображения объектов на основе нескольких простых элементов (рис. 8.1).
Рис. 8.1. Трехмерные объекты в различных ракурсах показа
Используем объектно-ориентированную методологию. Каждый элемент будем считать объектом трехмерного пространства, а несколько таких объектов образовывают модель сложного объекта. Для описания объектов используем классы C++. Процитируем автора языка C++ Б. Страустрапа: "Определите, какие классы вам нужны; предусмотрите полный набор операций для каждо-
[ го класса; опишите общие черты явным образом, используя наследова-
! ние" [24].
Сложный пространственный объект в нашей программе построим с использованием таких элементов: куб, сфера и пирамида. Фундамент и колонны бу-
дем считать производными элементами, их определим как множество кубов, специальным образом располагающихся в пространстве (рис. 8.2).
Рис. 8.2. Иерархия классов
В качестве базового элемента определим абстрактный класс фигуры с такими свойствами: размер, цвет, расположение в пространстве, описываемое координатами ее центра. Также предусмотрим для фигур возможность перемещения, изменения размера, цвета и возможность быть нарисованной. Такие общие свойства выразим в классе shape. В этом классе также предусмотрим операцию преобразования координат для отображения в определенной проекции (функция-член PrepareVertex).
Теперь обсудим способ отображения объектов. Поскольку у нас есть элементы-многогранники (куб и пирамида), то можно было бы использовать достаточно быстродействующую функцию Polygon API Windows для рисования граней. А удаление невидимых точек осуществлять сортировкой граней по глубине. Однако такой способ отображения в нашем случае не приемлем, Чуть позже мы покажем почему, а пока что обсудим довольно интересные нюансы объектно-ориентированного стиля программирования. Если бы у нас все объекты были многогранниками, то сортировка граней по глубине означала бы определенную последовательность рисования граней. Например,) сначала одну грань одного объекта, потом соответствующую грань другого \ объекта и так далее. Последовательность рисования в этом случае должна быть от самых дальних граней к самым близким. Однако это усложняет объектно-ориентированную реализацию программы, поскольку желательно было бы, чтобы объект был самодостаточным с точки зрения каждой операции, | выполняемой над ним, — а это невозможно, так как операция сортировки граней должна обеспечивать доступ к отдельным граням, а не только к объекту в целом. Хотя объектно-ориентированная методология не накладывает столь жестких ограничений на реализацию объектов, однако, такое нарушение самодостаточности (инкапсуляции) выглядит не очень эстетично.
Поскольку среди элементов кроме многогранников есть сфера, то метод сор- j тировки граней по глубине нельзя использовать, так как сфера — это не мно- j
гогранник, и она рисуется по пикселам (хотя можно было бы определить ее как многогранник, закрашенный, например, по методу Гуро, однако это намного сложнее, и в данном примере программы не рассматривается). Необходимо использовать Z-буфер, а функция Polygon его не поддерживает. Более того, в составе функций API Windows нет ни одной функции рисования, рассчитанной на использование Z-буфера. Такие функции мы вынуждены сконструировать сами. Относительно объектной ориентированности— метод Z-буфера позволяет полностью инкапсулировать операцию рисования объекта в виде одной функции-члена (мы ее назовем :: Draw). Один вызов функции Draw обеспечивает полный цикл отображения объекта соответствующего класса.
Текст программы (studex34. срр):
Скомпилируйте и запустите программу studex34. Необходимо предупредить, что цикл показа может затянуться надолго. В программе выполняется полный оборот камеры на 360 градусов с шагом в один градус. Время создания и отображение всех 361 кадров в соответствующих ракурсах на компьютере с процессором AMD K6-2, 300 МГц, в 24-битном видеорежиме составляло 807 секунд. То есть, на один кадр расходуется в среднем 807/361 = 2.24 секунды. Размеры окна не изменялись после запуска программы, это отвечает размерам изображения 392 на 239 пикселов. Необходимо признать, что эта программа демонстрирует черепашью скорость рендеринга.
8.1. Анализ и оптимизация программы
Каждую программу можно усовершенствовать. Можно попробовать уменьшить текст программы, уменьшить размер выполняемого файла, улучшить структурированность, модульность и так далее. В данном случае мы попытаемся повысить скорость рендеринга — уменьшить время формирования кадров изображения.
Как оптимизировать программу по быстродействию? Для этого необходимо выполнить анализ работы программы. В результате анализа нужно обнару-
жить операции, которые обуславливают быстродействие программы. Пос^ того как будут найдены критические места программы, можно сделать выв^ ды относительно конкретных путей оптимизации.
Для измерения времени выполнения операций в программе для Window можно воспользоваться функцией API GetLocalTime :
Необходимо предупредить, что миллисекунды измеряются не очень точно, поэтому для повышения точности измерения для некоторой отдельной операции можно делать цикл из многих (сотен, тысяч, ...) одинаковых операций (если вспомогательные операции создания цикла сами по себе не длительные). Кроме того, различные сеансы измерений могут давать различные значения, поэтому необходимо как-то усреднять результаты. Понятно, что все] измерения должны выполняться на одном и том же компьютере и обязатель-; но в одинаковых условиях выполнения программы. Также необходимо учи- ? тывать, что в полночь измерение времени может дать ошибку, — если переход на 0 часов случится в ходе измерений. Впрочем, я и не рекомендую вам по ночам засиживаться за компьютером — ночью надо спать.
Теперь приступим к анализу программы studex34. Вся работа по созданию объектов, их отображение в различных ракурсах и уничтожение объектов делается в теле функции DrawstudyExampie. Сделаем измерения времени ос-
новных операций. На создание объектов, открытие контекста, подготовку битмапа двойного буфера и создание Z-буфера расходуется менее десяти миллисекунд (измерения с точностью до процентов секунд дают 0.00). Таким образом, в ходе дальнейшего анализа сосредоточимся на цикле создания 361 кадра.
Как измерить время, расходуемое во всех 361 кадрах на выполнение функции ciearMyZbuf f er () ? Это сделаем способом, который можно назвать "способом контрольно-измерительного стенда". Такой "стенд" можно сделать на основе текста нашей программы, например, следующим образом:
//далее вычисляем разность в секундах и выводим результат
Разумеется, подобный способ измерений можно считать корректным лишь тогда, когда время выполнения функции CiearMyZbuffer () значительно больше, чем время выполнения операций организации цикла по j.
Время выполнения 361 операции ciearMyZbuffer составляет в среднем 2.1 секунды. Аналогично можно сделать измерения для PatBit— 0.06 сек., SetCameraviewMatrix — 0.00 сек., BitBit — 0.5 сек. Однако делать измерения времени для цикла отображения объектов таким "стендовым" способом нельзя. Для корректного создания изображения обязательно выполнение всех подготовительных операций в полном объеме. Для измерений времени здесь можно предложить другой способ. Суть его такова. Вначале измеряем время выполнения полного цикла создания изображений:
5
А потом исключаем анализируемую операцию:
и измеряем время выполнения без нее. Полный цикл — 807 сек., без исключенной операции — 2.6 сек. Назовем такой способ "временным исключением". Необходимо заметить, что цифру 2.6 можно было бы получить и иначе, если от времени полного цикла вычесть уже измеренное время других операций. Однако способ "временного исключения" предназначен в первую оче-j редь для тех случаев, когда измерение всех составных операций затруднено или не нужно. Продолжим измерения дальше.
Как мы видим, в цикле создания кадров на подготовительные операции расходуется мало времени в сравнении с отображением объектов. В ходе отображения объектов выполняется много операций. Какая из них самая длительная? Осуществим поиск способом "временного исключения". Однако для применения этого способа есть много ограничений. Сформулируем основные условия корректного использования данного способа.