ОПД.Ф.7 Практикум на ЭВМ 4 сем

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ
федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
«Мурманский государственный гуманитарный университет»
(ФГБОУ ВПО «МГГУ»)
УЧЕБНО-МЕТОДИЧЕСКИЙ КОМПЛЕКС
ДИСЦИПЛИНЫ
ПРАКТИКУМ НА ЭВМ, IV СЕМЕСТР
Основная образовательная программа подготовки специалиста по специальности
010501 «Прикладная математика и информатика»
Утверждено на заседании кафедры
математики и математических методов
в экономике факультета
физико-математического образования,
информатики и программирования
(протокол № 6 от 27 февраля 2013 г.)
Зав. кафедрой _______________О.М. Мартынов
______________________________
1.1 Автор программы: кандидат технических наук, доцент Ланина Н.Р.
1.2 Рецензент: доктор физико-математических наук, профессор Маренич Е.Е., кандидат
физико-математических наук, доцент Мостовской А.П.
1.3 Пояснительная записка:
Целью изучения курса «Практикум на ЭВМ» является подготовка студентов на
уровне, необходимом и достаточном для:
 усвоения материала специальных дисциплин;
 практической работы по специальности;
 формирования умения исследовать математические модели, обрабатывать и анализировать экспериментальные данные.
Основными задачами изучения данной дисциплины являются:
 формирование у студентов математической культуры и развитие логического
мышления;
 формирование целостной системы знаний о методах программирования в среде
Visual Studio 2005 C++ с использованием библиотеки основных классов MFC;
 обучение средствам графического стандарта OpenGL;
 обучение решению прикладных задач математическими методами;
 развитие способности творчески подходить к решению профессиональных задач.
В результате изучения курса студенты
должны знать: об основных понятиях и утверждениях, входящих в содержание дисциплины, методах программирования в среде Visual Studio 2005 C++ с использованием графических библиотек.
должны уметь:
 разрабатывать Windows-приложения в среде Visual Studio 2005 C++;
 использовать стандартные контрольные элементы;
 использовать Active-X контрольные элементы;
 дополнять свои Windows-приложения элементами GDI и OpenGL-графики;
 уметь организовать считывание информации с файла и запись её в файл;
 использовать полученные знания для решения математических и прикладных задач.
1.4. Курс входит в раздел дисциплин регионального вузовского компонента.
1.5. Объем дисциплины и виды учебной работы.
№
п/п
Шифр и наименование специальности
1
010501 «Прикладная математика и
информатика»
Курс
Семестр
Трудоемкость
2
4
130
Виды учебной работы в часах
Всего
ЛК
ПР/
ЛБ
аудит.
СМ
130
–
–
130
Сам.
работа
54
Вид итогового контроля
(форма отчетности)
зачёт
3
1.6 Содержание дисциплины.
1.6.1 Разделы дисциплины и виды занятий (в часах). Примерное распределение учебного
времени:
№
п/п
Наименование раздела, темы
1
Программирование в среде Visual Studio 2005 C++
Графический стандарт OpenGL
ИТОГО
2
Количество часов
для специальности 010501 «Прикладная
математика и информатика»
Всего
ЛК
ПР
ЛБ
Сам.
ауд.
раб.
70
–
–
70
30
60
130
–
–
–
–
60
130
24
54
1.6.2 Содержание разделов дисциплины.
Программирование в среде Visual Studio 2005 C++
Интерфейс программы. Окно проектов Workspace. Класс Окно-Рамка. Класс Приложение. События класса Окно-Рамка. Таблица откликов. Отладка программы
Генератор кода AppWizard. Диалоговая панель. Элементы управления: статический
текст, поле ввода, кнопка. Файл ресурсов. Программа ClassWizard. Наложение двух растровых изображений на кнопку
Приложение с вертикальной и горизонтальной прокруткой. Прокрутка с помощью
мыши и клавиатуры. Элементы управления: группирующая рамка, переключатель, флажок,
ползунок. Создание нового класса. Добавление пункта в Главное меню
Элементы управления: комбинированный список, графический список, полосы прокрутки, рисунок. Добавление кнопки в Панель инструментов. Наложение растрового изображения на управляющий элемент
Строка состояния. Перемещение мышью геометрических объектов. Устранение мерцания. Контекстное меню. Стандартное диалоговое окно класса CColorDialog
Использование элементов управления ActiveX. Стандартное диалоговое окно класса
CFileDialog. Сортировка массива записей по выбранному полю
Элементы управления: наборный счётчик. Изображение диаграммы ориентированного графа по заданным спискам смежности
Графический стандарт OpenGL
Основы OpenGL: интерфейс, архитектура, основные возможности, синтаксис команд.
Основные пространственные объекты. Пример простого приложения
Рисование геометрических объектов: точки, линии, треугольники, многоугольники
Специальные эффекты: прозрачность, туман. Плоскости отсечения. Трафареты
Текстурирование: подготовка текстуры, наложение текстуры на объект, текстурные
координаты
Материалы и освещение: модель освещения, спецификация материалов, описание источников света
4
1.6.3 Темы для самостоятельного изучения.
№ п/п
1
2
Наименование раздела
дисциплины.
Тема.
Программирование в
среде
Visual Studio 2005 C++
Графический стандарт
OpenGL
Форма самостоятельной работы
Зачётное задание
Зачётное задание
Форма контроля
выполнения
самостоятельной
работы
Проверка зачётного
задания
Количество
часов
Проверка зачётного
задания
30*
24*
1.7 Методические рекомендации по организации изучения дисциплины.
1.7.1 Тематика и планы лабораторных занятий по изученному материалу
Лабораторные занятия по теме
«Программирование в среде Visual Studio 2005 C++»
ЛБ № № 1-2. Работа № 1: Интерфейс программы. Окно проектов Workspace. Класс
Окно-Рамка. Класс Приложение. События класса Окно-Рамка. Таблица откликов. Отладка
программы
ЛБ № № 3-5. Работа № 2: Генератор кода AppWizard. Диалоговая панель. Элементы
управления: статический текст, поле ввода, кнопка. Файл ресурсов. Программа ClassWizard.
Наложение двух растровых изображений на кнопку
ЛБ № № 6-8. Работа № 3: Приложение с вертикальной и горизонтальной прокруткой.
Прокрутка с помощью мыши и клавиатуры. Элементы управления: группирующая рамка,
переключатель, флажок, ползунок. Создание нового класса. Добавление пункта в Главное
меню
ЛБ № № 9-11. Работа № 4: Элементы управления: комбинированный список, графический список, полосы прокрутки, рисунок. Добавление кнопки в Панель инструментов.
Наложение растрового изображения на управляющий элемент
ЛБ № № 12-14. Работа № 5: Строка состояния. Перемещение мышью геометрических
объектов. Устранение мерцания. Контекстное меню. Стандартное диалоговое окно класса
CColorDialog
ЛБ № № 15-17. Работа № 6: Использование элементов управления ActiveX. Стандартное диалоговое окно класса CFileDialog. Сортировка массива записей по выбранному
полю
ЛБ № № 18-20. Работа № 7: Элементы управления: наборный счётчик. Изображение
диаграммы ориентированного графа по заданным спискам смежности
Литература
1. Березин Б.И., Березин С.Б. Начальный курс С и С++. М.: ДИАЛОГ-МИФИ, 2001. 288 с.
2. Глушаков С.В. Программирование на Visual C++ / С.В. Глушаков, А.В.Коваль, С.А.
Черепнин; Худож.-оформ. А.С. Юхтман – М.: ООО «Издательство АСТ»; Харьков: «Фолио»,
2003. – 726 с.
3. Каев Артём. MFC шаг за шагом. Адрес в Internet: http://www.firststeps.ru/mfc/steps/
4. Круглински Д., Уингоу С., Шеферд Дж. Программирование на Microsoft Visual C++
6.0 для профессионалов / Пер. с англ. - СПб: Питер; М.: Издательско-торговый дом «Русская
редакция», 2001. - 864 с.
5. Культин Н. Delphi 3. Программирование на Object Pascal - СПб.: BHV - СанктПетербург, 1998. - 304 с.
6. Сазонов Д.О., Якунин М.С. Программирование на VC++. Интернет-сайт:
http://www_np_vspu_ac_ru.htm.
5
Лабораторные занятия по теме
«Графический стандарт OpenGL»
ЛБ № № 21-22. Работа № 1: Основы OpenGL: интерфейс, архитектура, основные возможности, синтаксис команд. Основные пространственные объекты. Пример простого приложения
ЛБ № № 23-24. Работа № 2: Рисование геометрических объектов: точки, линии, треугольники, многоугольники
ЛБ № № 25-26. Работа № 3: Специальные эффекты: прозрачность, туман. Плоскости
отсечения. Трафареты
ЛБ № № 27-28. Работа № 4: Текстурирование: подготовка текстуры, наложение текстуры на объект, текстурные координаты
ЛБ № № 29-30. Работа № 5: Материалы и освещение: модель освещения, спецификация материалов, описание источников света
Литература
1. Верма Р.Д. Введение в OpenGL. – М: Горячая линия – Телеком, 2004. – 303 с.
2. Девис Т., Нейджер Дж., Шрайнер Д. OpenGL. Руководство по программированию.
Библиотека программиста. 4-е издание. – СПб.: Питер, 2006. – 624 с.
3. Евченко А.И. OpenGL и DirectX: программирование графики. СПб.: Питер, 2006. –
350с.
4. Тарасов И. OpenGL., 2000. Интернет-сайт.
5. Тихомиров Ю. «Программирование трехмерной графики» BHV. – Санкт – Петербург, 2001.
1.8 Учебно-методическое обеспечение дисциплины.
1.8.1 Рекомендуемая литература:
основная:
1. Маликова Л. В., Пылькин А. Н. Практический курс по эл. Таблицам MS
EXEL.Уч.пособие для вузов. М: горячая линия-Телеком, 2004
2. Ланина Н. Р.3D studio max. Лабораторный практикум : учеб. пособие для студ. вузов,
обуч. по спец. "Прикладная математика" и по направл. "Прикладная математика и информатика" / Н. Р. Ланина, Л. В. Яковлева ; Федер. агентство по образованию, Мурм.
гос. пед. ун-т. - Мурманск : МГПУ, 2006. - 117 с. гриф
3. Могилев А.В. Практикум по информатике:учеб. Пособие для студ.вузов – М.: Академия 2001 – гриф
4. Яковлева Л. В.Базы данных : В 2-х ч.: практикум : учеб. пособие для студ. вузов, обуч.
по спец. 010200 и направл. 510200 "Прикладная математика и информатика" / Л. В.
Яковлева ; Федер. агентство по образованию, Мурм. гос. пед. ун-т. - Мурманск :
МГПУ, 2007 -.гриф
дополнительная:
1. Березин Б.И., Березин С.Б. Начальный курс С и С++. М.: ДИАЛОГ-МИФИ, 2001. - 288
с.
2. Верма Р.Д. Введение в OpenGL. – М: Горячая линия – Телеком, 2004. – 303 с.
3. Глушаков С.В. Программирование на Visual C++ / С.В. Глушаков, А.В.Коваль, С.А.
Черепнин; Худож.-оформ. А.С. Юхтман – М.: ООО «Издательство АСТ»; Харьков:
«Фолио», 2003. – 726 с.
4. Девис Т., Нейджер Дж., Шрайнер Д. OpenGL. Руководство по программированию.
Библиотека программиста. 4-е издание. – СПб.: Питер, 2006. – 624 с.
5. Евченко А.И. OpenGL и DirectX: программирование графики. СПб.: Питер, 2006. –
350с.
6
6. Каев Артём. MFC шаг за шагом. Адрес в Internet: http://www.firststeps.ru/mfc/steps/
7. Круглински Д., Уингоу С., Шеферд Дж. Программирование на Microsoft Visual C++ 6.0
для профессионалов / Пер. с англ. - СПб: Питер; М.: Издательско-торговый дом «Русская редакция», 2001. - 864 с.
8. Культин Н. Delphi 3. Программирование на Object Pascal - СПб.: BHV - СанктПетербург, 1998. - 304 с.
9. Сазонов Д.О., Якунин М.С. Программирование на VC++. Интернет-сайт:
http://www_np_vspu_ac_ru.htm.
10. Тарасов И. OpenGL., 2000. Интернет-сайт.
11. Тихомиров Ю. «Программирование трехмерной графики» BHV. – Санкт – Петербург,
2001.
1.9 Материально-техническое обеспечение дисциплины.
1.9.1 Электронный конспект лабораторных работ и заданий на самостоятельное выполнение
1.10 Примерные зачетные тестовые задания.
Задание №1. «Программирование в среде Visual Studio 2005 C++»
Пример задания
Разработать и реализовать Windows-приложение, позволяющее вычислить произведение Cmp двух матриц Amn и Bnp.
Предусмотреть возможность ввода матриц Amn и Bnp как с экрана, так и из входного
текстового файла.
Для изменения параметров m, n, p использовать контрольные элементы «Наборный
счётчик»
Для вывода на экран матриц Amn, Bnp, Cmp использовать три контрольных Active-X
элемента «Таблица».
Снабдить приложение Главным меню и Панелью инструментов.
Задание №2 «Графический стандарт OpenGL»
Разработать и реализовать компьютерную игру "Arconoid": летающий шарик, снизу
подставка, пользователь стрелками или мышкой управляет подставкой и отбивает шарик.
1.11 Примерный перечень вопросов к зачету (экзамену).
Программирование в среде Visual Studio 2005 C++
1. Интерфейс программы Visual Studio 2005 C++
2. Способы отладки программы
3. Элемент управления статический текст: добавление и модификация свойств
4. Элемент управления поле ввода: добавление, считывание числовой информации из
поля ввода, запись числовой информации в поле ввода
5. Элемент управления кнопка: добавление, подключение процедуры-обработчика
нажатия на кнопку, наложение двух растровых изображений на кнопку
6. Прокрутка с помощью мыши и клавиатуры
7. Элемент управления группирующая рамка: добавление, назначение элемента
8. Элемент управления переключатель: добавление и подключение
9. Элемент управления флажок: добавление и подключение
10. Элемент управления ползунок: добавление и подключение
11. Добавление пункта в Главное меню
7
12. Элемент управления комбинированный список: добавление и подключение
13. Элемент управления графический список: добавление и подключение
14. Элемент управления полоса прокрутки: добавление и подключение
15. Элемент управления рисунок: загрузка рисунка из графического файла
16. Добавление кнопки в Панель инструментов
17. Наложение растрового изображения на управляющий элемент
18. Строка состояния и её модификация
19. Перемещение мышью геометрических объектов. Устранение мерцания
20. Контекстное меню
21. Применение стандартного диалогового окна класса CColorDialog для смены цвета
геометрических объектов
22. Элемент управления наборный счётчик: добавление и подключение
8
Графический стандарт OpenGL
1. Основы OpenGL: интерфейс, архитектура, основные возможности, синтаксис команд
2. Основные пространственные объекты
3. Основные геометрические объекты
4. Организация специальных эффектов: прозрачность, туман
5. Плоскости отсечения и их применение
6. Трафареты и их применение для осуществления булевых операций
7. Текстурирование: подготовка текстуры, наложение текстуры на плоскую поверхность
8. Текстурирование: текстурные координаты, наложение текстуры на сложный пространственный объект
9. Освещение: модель освещения, описание источников света
10. Материалы: их спецификация и использование
1.12 Комплект экзаменационных билетов.
1.13 Примерная тематика рефератов.
Не предусмотрено Стандартом
1.14 Примерная тематика курсовых работ.
Не предусмотрено Стандартом
РАЗДЕЛ 2. Методические указания по изучению дисциплины и контрольные задания для студентов заочной формы обучения.
нет заочной формы обучения.
РАЗДЕЛ 3. Содержательный компонент теоретического материала.
ЧАСТЬ I. ПРОГРАММИРОВАНИЕ В СРЕДЕ
VISUAL STUDIO 2005 C++
Класс "Окно-Рамка". Класс "Приложение"
Дважды щелкнув левой кнопкой мыши имя файла MainFrm.h, откройте
этот файл и просмотрите его. В этом заголовочном файле объявлен класс "ОКНО_РАМКА", названный нами CMainWnd, и его конструктор. Этот класс объявлен, как производный от стандартного класса CFrameWnd.
Закройте файл MainFrm.h.
Откройте файл MyPr01.h и просмотрите его. В этом заголовочном файле
объявлен класс"ПРИЛОЖЕНИЕ", названный нами CMyApp, его конструктор и
функция InitInstance(). Этот класс объявлен, как производный от стандартного
класса CWinApp.
9
В каждой программе, написанной на языке на С++, есть главная функция
программы; в Dos − это main(), в Windows − WinMain(). Эта функция обеспечивает запуск программы. Она проверяет операционную среду, выполняет некоторые настройки и, если все нормально, непосредственно передает управление Вашему коду. Класс CWinApp, содержащийся в MFC, и включает главную
функцию программы, которая явно в тексте программы не присутствует.
Наш класс CMyApp, являясь потомком класса CWinApp, унаследовал все
его свойства и методы. В этом классе мы объявили конструктор по умолчанию
(без параметров). Он необходим, т.к. без него программу не удастся скомпилировать.
Закройте файл MyPr01.h.
Откройте файл MainFrm.cpp и просмотрите его.
Класс CMainWnd ("ОКНО_РАМКА") является производным от стандартного класса CFrameWnd, который отвечает за работу окна программы в стиле
одного документа (SDI single document interface). Он создает окно, управляет
сообщениями и т.д. В конструкторе этого класса мы вызвали функцию создания
окна Create.
Закройте файл MainFrm.cpp.
Откройте файл MyPr01.cpp и просмотрите его.
Родительский класс CWinApp имеет виртуальный метод InitInstance()
("заглушку"). Для дочернего класса CMyApp в нашей программе создан свой
метод в виде функции InitInstance(). Этот метод должен возвращать ненулевое
значение, если инициализация прошла нормально и 0 в противном случае. Он
предназначен, чтобы Вы могли описать класс окна CMainWnd и отобразить окно на экране.
Родительский класс CWinApp содержит общедоступный указатель на
класс окна m_pMainWnd. Если по окончании работы функции InitInstance() он
будет равен нулю, то приложение завершится. И, естественно, после завершения приложения он обнуляется.
Строкой
m_pMainWnd=new CMainWnd();
мы присваиваем этому указателю адрес класса CMainWnd.
Функция
ASSERT(m_pMainWnd)
сравнит
значение
указателя
m_pMainWnd с нулем. Если объект "ОКНО_РАМКА" по какой-либо причине
не был создан, то значение m_pMainWnd окажется равно нулю и, благодаря
функции ASSERT, Вы получите сообщение об ошибке с указанием имени
файла и номера строки, в которых произошла эта ошибка.
Так как m_pMaiWnd имеет то же значение, что и CMainWnd, то мы используем эту переменную, чтобы вывести окно на экран.
В строке
CMyApp theApp;
объявляется один-единственный объект theApp класса CMyApp. Так осуществляется запуск приложения.
10
События класса "ОКНО_РАМКА"
Чтобы добавить функцию, реагирующую на внешние воздействия (такие
функции называют обработчиками сообщения), программист обязан:
 объявить функцию (в заголовочном файле);
 внести соответствующее сообщение в таблицу откликов (в файле
реализации);
 создать текст функции (в файле реализации).
Отладка программы
Часто при отладке программы необходимо узнать текущее значение некоторой переменной, которая изменяется "где-то там внутри...". Проще всего
сделать это с помощью функции AfxMessageBox.
К сожалению, отладка программ с помощью оператора AfxMessageBox,
мягко говоря, не всегда удобна. Например, Вам необходимо отследить значение
переменной внутри цикла. В этом случае Вы быстро выйдете из себя, раз за разом нажимая ОК, чтобы закрыть очередное окно AfxMessageBox.
Среда программирования Visual C++ предоставляет возможность разрабатывать приложение в режиме отладочной сборки (Debug mode), а отлаженная
готовая программа собирается заново в режиме окончательной сборки (Release
mode). Исполняемые файлы, собранные в режиме Release, имеют меньший размер и работают быстрее. Однако на стадии разработки программы удобнее работать в режиме Debug.
Контроль вводимых символов
Самый простой способ изменить поведение любого элемента управления (в том числе и поля ввода) − воспользоваться инструментом MFCбиблиотеки, предназначенным для создания оконных подклассов (window subclassing). При использовании редактора диалоговых окон в диалоговом ресурсе
размещается обычный элемент управления, а потом на языке С++ пишется новый класс, содержащий обработчики сообщений для тех событий, которые Вы
хотите обрабатывать самостоятельно.
Мы создадим новый класс (назовём его CEditTF), производный от класса
CEdit, и создадим обработчик сообщения WM_CHAR, представляющий собой
реакцию на ввод символов с клавиатуры.
1. Создаём новый класс
Щёлкните на вкладке Resource View строку MyPr02 (другими словами,
перейдите на самый высокий уровень проекта) и после этого выполните цепочку команд:
11
Главное меню: Project > Add Class.
В открывшемся окне Add Class в качестве Categories выберите MFC, в качестве Templates – MFC Class и нажмите кнопку Add.
Перед Вами открылось окно MFC Class Wizard. В поле Class name этого
окна введите имя нового класса: CEditTF, а в списке Base class в качестве базового выберите класс CEdit. Нажмите Finish, закрывая окно.
2. Создаём обработчик сообщения WM_CHAR
Откройте вкладку Class View окна проектов. В списке классов выделите
CEditTF и откройте окно его свойств (правая кнопка мыши). В окне свойств с
помощью кнопки
перейдите на вкладку сообщений и выберите там сообщение WM_CHAR. В открывшемся справа списке выберите строку <Add> OnChar().
Открылся сгенерированный файл EditTF.cpp и появилась заготовка кода
функции OnChar. Замените текст этой процедуры следующим текстом:
if (
isdigit(nChar) || // если цифра
iscntrl(nChar) ||
// или управляющий символ
nChar==45 ||
// или минус (45 - ASCII-код минуса)
nChar==46 )
// или точка (46 - ASCII-код точки)
{
CEdit::OnChar(nChar, nRepCnt, nFlags); // ...то вывести символ на экран
}
else
{
if (nChar==44)
// 44 - ASCII-код запятой
{
AfxMessageBox("Для отделения дробной части используйте точку.");
}
else
{
AfxMessageBox("Введён нечисловой символ!");
}
}
Теперь нам надо «донести» информацию о новом классе до сведения
класса CMyPr02View.
12
3. Добавляем переменную класса
Перейдите на вкладку ClassView окна проектов и раскройте список
MyPr02 classes. Щелкните правой кнопкой мыши CMyPr02View и в открывшемся контекстном меню выберите Add > Add Variable.
В результате перед Вами появилось одноимённое окно. В качестве типа
переменной (Variable Type) введите CEditTF. В поле Variable Name присвойте
новой переменной имя m_EditTF. Ничего больше не меняя, нажмите Finish.
Перейдите на вкладку Solution Explorer окна проектов. Раскройте списки:
MyPr02, Source files, Header files. В списке Header files найдите файл
MyPr02View.h (заголовочный файл класса «вид»). Дважды щелкнув по нему
левой кнопкой мыши, откройте этот файл. Убедитесь, что в его текст добавлены
строки:
#include "EditTF.h"
(в начало файла)
и
public:
CEditTF m_EditTF;
(в раздел Generated message map functions)
Они появились после добавления новой переменной. Следует отметить,
что Вы могли внести их сами, и тогда не надо было пользоваться командой Add
Variable. Сохраните файл MyPr02View.h и закройте его.
4. Откройте файл MyPr02View.cpp и найдите в нём функцию инициализации OnInitialUpdate. Добавьте в конец этой функции строки, которые позволят
связать переменную m_EditTF нового класса с управляющим элементом, имеющим идентификатор IDC_EDIT_TF:
if (m_EditTF.m_hWnd==NULL)
{
m_EditTF.SubclassDlgItem(IDC_EDIT_TF, this);
}
5. Соберите приложение и запустите его на выполнение. Убедитесь, что
в поле ввода появляется только числовая информация.
Добавление пункта в Главного меню
1. Добавьте в раздел Implementation файла MyPr03View.h объявление открытых переменных, в которые мы перегрузим данные из диалогового окна:
public:
int m_nType, m_nSize;
13
BOOL m_bColorRed, m_bColorGreen, m_bColorBlue;
2. Пусть наше диалоговое окно открывается через пункт Главного меню.
Добавим в Главное меню пункт Paint (Нарисовать) с двумя командами: Input
Data (Ввести Данные) и Clear Screen (Очистить Экран). Для этого выполните
цепочку команд:
вкладка ResourceView окна проектов > список Menu > дважды щелкнуть левой
кнопкой мыши IDR_MAINFRAME.
Перед Вами открылось окно редактора ресурсов.
Щелкните расположенную в конце (после пункта Help) ячейку Type Here
и введите текст: Paint.
Перейдите в ту ячейку, которая появилась под пунктом Paint и введите
&Input Data. Буква, которая стоит после символа & (в нашем случае I), будет
подчеркнута. Именно эта буква определяет быструю клавишу. В окне свойств
этого пункта меню ячейки (щёлкнуть ячейку правой кнопкой мыши) в поле
идентификатора ID введите ID_INPUTDATA, в поле всплывающей подсказки
Prompt − Click, to open dialog. Эта подсказка сообщит пользователю, что при
нажатии данной клавиши откроется окно диалога. Закройте окно свойств.
В ячейке, которая появилась под пунктом Input Data, введите &Clear
Screen. В поле идентификатора ID введите ID_CLEARSCREEN, в поле всплывающей подсказки Prompt − Click, to clear screen. Закройте окно свойств.
Выделите ячейку Paint и перетащите ее левой кнопкой мыши влево, вставив между пунктами Edit и View. У Вас должно получиться следующее:
3. Сохраните файл ресурсов MyPr03.rc на диске: вкладка ResourceView
окна проектов > Menu > правой кнопкой мыши щелкнуть IDR_MAINFRAME и
выбрать Save MyPr03.rc.
4. Для нового пункта меню создадим обработчик сообщения COMMAND.
Щёлкните правой кнопкой мыши ячейку Input Data и в открывшемся контекстном меню выберите команду Add Event Handler (Добавить Событие).
Перед Вами открылось окно Event Handler Wizard. В списке Class List выберите класс CMyPr03View. Убедитесь, что в списке Message type указано сообщение COMMAND и нажмите кнопку Add and Edit (Добавить и Редактировать).
В текст функции OnInputdata добавьте код:
14
CMyPr03Dialog dlg;
// Объявляем переменную dlg класса
CMyPr03Dialog
dlg.DoModal();
// Открыть модальное диалоговое окно
// Перегрузить данные из диалогового окна в переменные класса CMyPr03View
m_nType=dlg.m_nObject;
m_nSize=dlg.m_nSlider;
m_bColorRed=dlg.m_bRed;
m_bColorGreen=dlg.m_bGreen;
m_bColorBlue=dlg.m_bBlue;
5. Добавьте в файл MyPr03View.cpp оператор include:
#include “MyPr03Dialog.h”
6. Соберите проект и запустите программу на выполнение.
Щелкните кнопку Paint главного меню. Подведите курсор к строке Input
Data, не нажимая ее. В нижней строке окна, строке состояния, Вы можете
прочесть подсказку Click, to open dialog, которую внесли в поле Prompt свойств
пункта меню.
Обратите внимание, что команда Clear Screen пока не доступна. Так и
должно быть, - ведь мы еще не добавили к проекту обработчик этой команды.
Откройте диалоговое окно, щелкнув строку меню Input Data, и убедитесь,
что в качестве выбранного объекта помечена окружность, а в качестве выбранного цвета − красный. Пощелкайте переключатели и флажки, выбирая другой
объект и другой цвет.
Снова щелкните кнопку Paint, после чего нажмите клавишу «i» клавиатуры. Как видите, быстрая клавиша исправно работает: диалоговое окно послушно открылось.
Добавление кнопки на Панель инструментов
В грамотно написанной программе основные команды Главного меню,
как правило, дублируются кнопками Панели инструментов (Toolbar). Добавлять новые пункты в Главное меню Вы уже умеете. На этот раз заставим наше
приложение открывать окно диалога не только с помощью команды Главного
меню, но и с помощью кнопки, расположенной на Панели инструментов.
1. Добавьте в раздел Implementation файла MyPr04View.h объявление переменных, в которые мы перегрузим данные из диалогового окна:
private:
int EllipseA, EllipseB, EllipseFill, EllipseColor;
2, 3. Добросовестно отработайте пункты 2 и 3 раздела «Добавление команды в Главное меню» предыдущего раздела.
15
4. Для нового пункта меню создадим обработчик сообщения COMMAND.
Щёлкните правой кнопкой мыши ячейку Input Data и в открывшемся контекстном меню выберите команду Add Event Handler (Добавить Событие).
Перед Вами открылось окно Event Handler Wizard. В списке Class List выберите класс CMyPr04View. Убедитесь, что в списке Message type указано сообщение COMMAND и нажмите кнопку Add and Edit (Добавить и Редактировать).
В текст функции OnInputdata добавьте код:
CMyPr04Dialog dlg;
//
Объявляем
переменную
dlg
класса
CMyPr04Dialog
dlg.DoModal();
// Открыть модальное диалоговое окно
// Перегрузить данные из диалогового окна в переменные класса CMyPr04View
EllipseA = dlg.m_nA;
EllipseB = dlg.m_nB;
EllipseFill = dlg.m_nFill;
5. Добавьте в файл MyPr04View.cpp оператор include:
#include “MyPr04Dialog.h”
и сохраните файл MyPr04View.cpp.
6. Редактируем ресурс растрового изображения. Выполните цепочку команд:
вкладка ResourceView окна проектов > список Toolbar > дважды щелкнуть левой кнопкой мыши IDR_MAINFRAME.
В открывшемся редакторе ресурсов левой кнопкой мыши щелкните последнюю в ряду кнопок пустую кнопку и нанесите на нее какое-нибудь изображение.
В окне свойств добавленной кнопки в поле идентификатора укажите тот
же идентификатор ID_INPUTDATA, который имеет соответствующая команда Главного меню.
Обратите внимание, что в поле подсказки Prompt надо одну и ту же
надпись, разделенную символом \n (новая строка), повторить дважды. Надпись
16
слева от этого символа будет появляться в строке состояния, а надпись справа
 во всплывающей подсказке, при наведении на кнопку курсора.
Закройте редактор ресурсов.
7. Сохраните файл ресурсов MyPr04.rc на диске.
8. Соберите и запустите Ваше приложение. Убедитесь, что при наведении
мышью курсора на новую кнопку появляются обе подсказки (и всплывающая, и
на панели состояния). Убедитесь также, что диалоговое окно открывается обоими способами  с помощью Главного меню и с помощью Панели инструментов.
Подключение элементов управления «полосы прокрутки»
Подключим сначала горизонтальную полосу прокрутки.
1. Напомню, что ранее с этим элементом управления мы связали переменную m_nA. Изменим ее начальное
значение. Откройте файл
MyPr04Dialog.cpp. В тексте конструктора CMyPr04Dialog найдите строку:
, m_nA(0)
Замените 0 на 100.
2. Включите в файл CMyPr04Dialog.h, в самое начало объявления класса,
следующие строки:
// минимальное и максимальное значения для горизонтальной полосы прокрутки
enum {nMin_H=10};
enum {nMax_H=150};
3. Перед оператором return вставьте в текст функции OnInitDialog (файл
CMyPr04Dialog.cpp) следующий код:
// Создаем переменную pSB_H, как указатель на элемент класса CScrollBar
// и связываем эту переменную с элементом управления,
// имеющим идентификатор IDC_SCROLLBAR_H
CScrollBar* pSB_H=(CScrollBar*)GetDlgItem(IDC_SCROLLBAR_H);
// Устанавливаем границы изменения значений горизонтальной полосы прокрутки
pSB_H->SetScrollRange(nMin_H, nMax_H);
// Устанавливаем начальное положение тумблера
pSB_H->SetScrollPos(m_nA);
// Объявляем строковую переменную strTextH
CString strTextH;
// В строковую переменную заносим значение, на которое указывает тумблер
17
strTextH.Format("%d", pSB_H->GetScrollPos());
// Выводим это значение в статическое
IDC_STATIC_H
SetDlgItemText(IDC_STATIC_H, strTextH);
поле
с
идентификатором
4. Создадим обработчик сообщения WM_HSCROLL, который
 «заставит» тумблер полосы прокрутки оставаться в новом положении,
 позволит обновить статический текст в соответствии с текущим положением тумблера.
Откройте вкладку Class View окна проектов. В списке классов выделите
CMyPr04Dialog и откройте окно его свойств (правая кнопка мыши). В окне
свойств перейдите на вкладку сообщений Message и выберите там сообщение
WM_HSCROLL.
Замените текст функции OnHScroll на:
int nTemp1, nTemp2;
// Текущее положение тумблера считываем в переменную nTemp1
nTemp1=pScrollBar->GetScrollPos();
// Обрабатываем ситуацию в зависимости от того,
// какое действие изменило положение тумблера
switch(nSBCode) //
{
case SB_THUMBPOSITION: // передвинули тумблер мышью
// устанавливаем новое положение тумблера на отметку nPos
pScrollBar->SetScrollPos(nPos);
break;
case SB_LINELEFT: // передвинули тумблер кнопкой со стрелкой влево
nTemp2=(nMax_H-nMin_H)/50;
if ((nTemp1-nTemp2)>nMin_H)
// если не уперлись в левую границу, сдвигаемся влево
{ nTemp1-=nTemp2 ;}
else
{nTemp1=nMin_H;}
// устанавливаем новое положение тумблера на отметку nTemp1
pScrollBar->SetScrollPos(nTemp1);
break;
case SB_LINERIGHT: // передвинули тумблер кнопкой со стрелкой вправо
nTemp2=(nMax_H-nMin_H)/50;
if ((nTemp1+nTemp2)<nMax_H)
// если не уперлись в правую границу, сдвигаемся вправо
{ nTemp1+=nTemp2 ;}
else
{nTemp1=nMax_H;}
// устанавливаем новое положение тумблера на отметку nTemp1
18
pScrollBar->SetScrollPos(nTemp1);
break;
}
// Объявляем строковую переменную strTextH
CString strTextH;
// В строковую переменную заносим значение, на которое указывает тумблер
strTextH.Format("%d", pScrollBar->GetScrollPos());
// Выводим это значение в статическое поле с идентификатором
IDC_STATIC_H
SetDlgItemText(IDC_STATIC_H, strTextH);
// Обновляем значение переменной m_nA
m_nA=pScrollBar->GetScrollPos();
5. Сохраните файл MyPr04Dialog.cpp.
6. Соберите проект и запустите программу на выполнение. Открыв диалоговое окно, убедитесь, что горизонтальная полоса прокрутки «заработала»,
причем начальное положение тумблера соответствует позиции 100. Закройте
приложение.
Подключение элемента управления «комбинированный список»
Ранее мы связали с этим элементом управления переменную m_nFill. Изменим ее начальное значение. Откройте файл MyPr04Dialog.cpp. В тексте конструктора CMyPr04Dialog найдите строку
, m_nFill(0)
Напомню, что режим заполнения эллипса «нет заливки» имеет в нашем
комбинированном списке номер 0, режим «штриховка»  номер 1, режим
«сплошная заливка»  номер 2.
Чтобы по умолчанию был выбран режим «сплошная заливка», замените
0 на 2.
Если пользователь выберет другой режим, то значение переменной
m_nFill автоматически изменится.
Сохраните файл MyPr04Dialog.cpp и закройте его.
Соберите проект и запустите программу на выполнение. Открыв диалоговое окно, убедитесь, что комбинированный список исправно «работает», причем начальный выбор соответствует режиму «сплошная заливка». Закройте
приложение.
Создаем контекстное меню
Рассмотрим, как организовать контекстное меню (floating pop-up menu),
которое пользователь открывает щелчком правой кнопки мыши.
19
1. Чтобы добавить в файл ресурсов новое пустое меню, перейдите на
вкладку Resource View, щёлкните правой кнопкой мыши строку Menu и в открывшемся контекстном меню выберите команду Add Resource. Перед Вами
открылось одноимённое окно. Выберите в нём пункт Menu и щёлкните кнопку
New.
2. Откройте окно редактора ресурсов (вкладка ResourceView окна проектов > список Menu > дважды щелкнуть левой кнопкой мыши IDR_MENU1).С
помощью редактора ресурсов добавьте в меню пункты:
У первой команды замените идентификатор на ID_COLOR_ELLIPSE, а у
второй  на ID_COLOR_BACKGRAUND.
3. Не закрывая окно свойств, на панели ResourceView щёлкните левой
кнопкой мыши идентификатор IDR_MENU1. В окне свойств смените идентификатор на IDR_MENU_CONTEXT. Обратите внимание, что в списке Language
уже выбран русский язык. Закройте окно свойств.
4. Вставьте обработчик сообщения WM_CONTEXTMENU (вкладка Class
View > класс выделите CMyPr05View > окно свойств (правая кнопка мыши) >
вкладка сообщений).
Вставьте в текст функции OnContextMenu:
CMenu menu; // Создаем меню
menu.LoadMenu(IDR_MENU_CONTEXT); // Связываем созданное меню с ресурсом
// Конструируем контекстное меню так, чтобы оно раскрывалось справа от курсора и
// пункты меню выравнивались по левому краю
menu.GetSubMenu(0)>TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,
point.x,point.y,
this);
5. В заголовке процедуры OnContextMenu снимите комментарии с pWnd
и point:
void CMyPr05View::OnContextMenu(CWnd* pWnd, CPoint point)
6. Соберите приложение и запустите. Щелкнув правой кнопкой мыши,
убедитесь, что контекстное меню появляется (правда, пока ничего не делает).
20
Команды контекстного меню можно сопоставить с обработчиками тем же способом, что и команды Главного меню.
Добавление контрольного ActiveX-элемента управления
Установим в проект ActiveX-элемент управления FlexGrid, позволяющий
работать с таблицей. Для этого выполните следующие действия:
1. откройте палитру элементов управления (пункт View Главного меню >
ToolBox);
2. щёлкнув правой кнопкой мыши в любом месте палитры, откройте контекстное меню, в котором выберите команду: Choose Item;
Перед Вами открылось окно Choose Toolbox Items. Перейдите на вкладку
COM Components этого окна.
Здесь хранится масса полезных элементов управления, позволяющих работать с анимацией, со звуком, с сетью Интернет и т.д. В настоящее время нас
интересует элемент Microsoft FlexGrid Control, version 6.0:
Поставив «галочку», выберите этот элемент и нажмите OK.
В результате этих действий в самом низу палитры Toolbox элементов
управления появился новый элемент.
21
Перетащите мышью с палитры в создаваемое диалоговое окно только что
добавленный элемент «Таблица» (Microsoft FlexGrid Control, version 6.0).
ЧАСТЬ II. ГРАФИЧЕСКИЙ СТАНДАРТ OpenGL
Введение
Библиотека OpenGL представляет собой интерфейс программирования
трехмерной графики. Единицей информации является вершина, из них состоят
более сложные объекты. Программист создает вершины, указывает как их соединять(линиями или многоугольниками), устанавливает координаты и параметры камеры и ламп, а библиотека OpenGL берет на себя работу создания
изображения на экране. OpenGL идеально подходит для программистов, которым необходимо создать небольшую трехмерную сцену и не задумываться о
деталях реализации алгоритмов трехмерной графики. Для профессионалов, занимающихся программированием трехмерной графики, библиотека тоже будет
полезной, т.к. она представляет основные механизмы и выполняет определенную автоматизацию. Используя OpenGL вы с легкостью создадите трехмерные
поверхности, наложите на них текстуры, осветите источниками света, сможете
сделать эффект тумана, прозрачности, смешивания цветов, а также сможете
наложить трафарет, передвигать объекты сцены, лампы и камеры по заданным
траекториям, сделав, тем самым, анимацию. OpenGL непосредственно не поддерживает работу с устройствами ввода, такими как мышь или клавиатура, т.к.
эта библиотека является платформенно независимой. Но вы можете задействовать функции конкретной операционной системы, под которую вы пишите
свою программу, или воспользуйтесь надстройками над OpenGL, такими как
библиотеки GLUT или GLAUX. Тем самым, ваша программа заживет новой
жизнью. Возможности просто безграничны!
Функция glColor3d
Функция glColor3d устанавливает текущий цвет, которым будут рисоваться фигуры. Тут нужно пояснить, как устанавливается цвет, и общую философию в названии функций OpenGL. Цвет устанавливается четырьмя параметрами: красный, синий, зеленый и прозрачность. Эти параметры варьируются в
диапазоне от нуля до единицы. Четвертый параметр нам пока не нужен, поэтому мы вызвали glColor с тремя параметрами. В этом случае, значение четвертого параметра, прозрачности, по умолчанию считается равным единице, т.е. аб-
22
солютно непрозрачным, ноль - будет абсолютно прозрачным. Так как в языке
Си нет перегрузки функций, то применяется следующий синтаксис вызова
функций - FuncionName[n=число параметров][тип параметров]. Доступны следующие типы:









b - GLbyte байт
s - GLshort короткое целое
i - GLint целое
f - GLfloat дробное
d - GLdouble дробное с двойной точностью
ub - GLubyte беззнаковый байт
us - GLushort беззнаковое короткое целое
ui - GLuint беззнаковое целое
v - массив из n параметров указанного типа
В нашем случае, glColor3d означает, что в функцию передаются три параметра типа GLdouble. Также можно было вызвать glColor3i, т.е. три параметра
типа GLint. Если тип параметров короткое целое, целое, байт или длинное, то
компонент цвета приводится к диапазону [0,1]. Приведение к этому диапазону
осуществляется следующим образом. В случае беззнакового типа наибольшее
возможное значение приводится к единице, ноль к нулю. В случае знакового
типа максимальное значение приводится к единице или к минус единице, а минус единица будет приведена к единице. Мудрено, сразу и не поймешь. На
практике вы будете пользоваться одним из трех случаев, рассмотренных в качестве примера ниже. Например, для беззнакового байта приведение будет осуществлено по следующей формуле:
значение_переменной_хранимой_в_байте / 255,
т.к. 255 максимальное число, хранимое в одном байте. Функция glColor3dv
означает, что в качестве параметров передается массив из трех элементов типа
GLdouble. Например:
double array[] = {0.5, 0.75, 0.3, 0.7};
...
glColor3dv(array);
glColor3ub(200,100,0);
glColor3d(0.25,0.25,0);
glColot3ub(0,100,0);
glColor3ub(0,0,255);
//
//
//
//
приводится к 200/256, 100/256, 0,256
темно-желтый
темно-зеленый
синий
Трехмерные фигуры




auxSolidSphere (width) // сфера
auxSolidCube(width) // куб
auxSolidBox(width, height, depth) // коробка
auxSolidTorus(r,R) // тор
23







auxSolidCylinder(r,height) // цилиндр
auxSolidCone(r,height) // конус
auxSolidIcosahedron(width) // многогранники
auxSolidOctahedron(width)
auxSolidTetrahedron(width)
auxSolidDodecahedron(width)
auxSolidTeapot(width) // рисует чайник
Переход к новым координатам
Для того чтобы изобразить сферу в точке (x0,y0,z0), надо переместить
начало координат в эту точку, т.е. надо перейти к новым координатам. Эта процедура, довольно распространенная при программировании графики и анимации. Часто бывает очень удобно сместить координаты в новую точку и повернуть их на требуемый угол, и ваши расчеты резко упростятся. Для перехода к
новым координатам в OpenGL есть две функции:


glTranslated( x,y,z )
glRotated(,x0,y0,z0 )
Первая функция сдвигает начало системы координат на (x, y, z).
Вторая - поворачивает на угол  против часовой стрелки вокруг вектора
(x0,y0,z0). Теперь, стоит сказать еще о двух очень важных функциях:


glPushMatrix()
glPopMatrix()
Они предназначены для сохранения и восстановления текущих координат. Гораздо удобнее с помощью glPushMatrix() сохранить текущие координаты, потом сдвигаться, вертеться, как вам угодно, а после, вызывом glPopMatrix,
вернуться к старым координатам.
Геометрические примитивы
Примитивы создаются следующим образом:
glBegin(GLenum mode); // указываем, что будем рисовать
glVertex[2 3 4][s i f d](...); // первая вершина
...
// тут остальные вершины
glVertex[2 3 4][s i f d](...); // последняя вершина
glEnd();
// закончили рисовать примитив
Сначала вы говорите, что будете рисовать - glBegin с соответствующим
параметром. Возможные значения mode перечислены ниже в таблице. Далее вы
указываете вершины, определяющие объекты указанного типа. Обычно, вы будете задавать вершину одним из четырех способов.
24
glVertex2d(x,y);
glVertex3d(x,y,z);
glVertex2dv(array);
glVertex3d(array);
//
//
//
//
две переменных
три переменных
массив из двух
массив из трех
типа double
типа double
переменных типа double
переменных типа double
И, наконец, вы вызваете glEnd, чтобы указать, что вы закончили рисовать
объекты типа, указанного в glBegin. Далее мы подробно разберем создание всех
примитивов.
Значение mode
GL_POINTS
GL_LINES
GL_LINE_STRIP
Описание
Каждый вызов glVertex задает отдельную точку.
Каждая пара вершин задает отрезок.
Рисуется ломаная.
Рисуется ломаная, причем ее последняя точка соединяGL_LINE_LOOP
ется с первой.
GL_TRIANGLES
Каждые три вызова glVertex задают треугольник.
GL_TRIANGLE_STRIP Рисуются треугольники с общей стороной.
Тоже самое, но по другому правилу соединяются верGL_TRIANGLE_FAN
шины, вряд ли понадобится.
Каждые четыре вызова glVertex задают четырехугольGL_QUADS
ник.
GL_QUAD_STRIP
Четырехугольники с общей стороной.
GL_POLYGON
Многоугольник.
Построение поверхностей
Существует набор функций для построения сфер, цилиндров и дисков. Эти функции
представляют очень мощный контроль за построением трехмерных объектов. Непосредственно рисовать вы будете, используя следующие функции: 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. Чем
25
больше объект, тем больше нужно разбиений. Число разбиений вдоль и поперек я выставляю
одинаковыми. Сначала вы должны создать объект типа GLUquadricObj с помощью функции
gluNewQuadric. Теперь устанавливаете свойства с помощью функции gluQuadricDrawStyle.
Доступны стили: GLU_FILL - рисуется сплошной объект, GLU_LINE - проволочный объект,
GLU_POINT - рисуются только точки. Рисуете то, что хотите. И не забудьте удалить созданный объект, воспользовавшись gluDeleteQuadric.
Плоскости отсечения
Если вам требуется нарисовать сферу или любой другой объект урезанным, то
плоскости отсечения это то, что вам надо. Плоскостей отсечения может быть шесть штук. По
умолчанию они все запрещены. Плоскость отсечения включается командой
glEnable(GL_CLIP_PLANE0). Ноль на конце GL_CLIP_PLANE означает нулевую плоскость;
можно указать один, два, три и т.д. Сама плоскость устанавливается функцией glClipPlane.
Первый аргумент этой функции - это плоскость, второй - это массив из четырех элементов, в
котором хранятся коэффициенты уравнения плоскости. Для тех, кто не помнит уравнения
плоскости в трехмерном пространстве, напоминаю: A*x+B*y+C*z+D = 0. Вот эти самые
A,B,C,D и являются теми четырьмя коэффициентами.
Текстурирование
Часто возникает потребность накладывать изображение на трехмерные
объекты и поворачивать/сдвигать их. Для этих целей существую текстуры.
Также текстуры помогут вам покрыть весь объект в виде мозаики. Скажем, когда у вас имеется кирпичная стена, то вам не надо загружать изображение с кучей кирпичей. Достаточно загрузить один кирпич и указать, что эту текстуру
нужно
размножить
по
всей
плоскости.
Сначала мы разберем создание и наложение текстур на плоскость. Затем
рассмотрим наложение текстур на криволинейные поверхности.
Для того, чтобы наложить текстуру на объект, вы должны:
1.
2.
3.
4.
5.
6.
7.
Загрузить графический файл в память
Создать имя-идентификатор текстуры
Сделать его активным
Создать саму текстуру в памяти
Установить параметры текстуры
Установить параметры взаимодействия текстуры с объектом
Связать координаты текстуры с объектом
Материал
Материал может рассеивать, отражать и излучать свет. Свойства материала устанавливаются при помощи функции
glMaterialfv(GLenum face, GLenum pname, GLtype* params)
26
Первый параметр определяет грань, для которой устанавливаются
свойства. Он может принимать одно из следующих значений:
GL_BACK
GL_FONT
GL_FRONT_AND_BACK
задняя грань
передняя грань
обе грани
Второй парметр функции glMaterialfv определяет свойство материала,
которое будет установлено, и может принимать следующие значения:
GL_AMBIENT рассеянный свет, показанный в тени
GL_DIFFUSE рассеянный свет, показанный на освещённой стороне
GL_SPECULAR отраженный свет
GL_EMISSION излучаемый свет
GL_SHININESS степень отраженного света
GL_AMBIENT_AND_DIFFUSE оба рассеянных света
Цвет задается в виде массива из четырех элементов - RGBA. В случае
GL_SHININESS params указывает на число типа float, которое должно быть в
диапазоне от 0 до 128.
Лампы и их свойства
Все параметры лампы задаются с помощью функции glLight, которая
имеет следующий прототип:
void glLight[if][v](
GLenum light,
GLenum pname,
GLfloat param)
Первый аргумент определяет номер лампы. Его можно задавать двумя
способами. Первый - явно указать GL_LIHGTi, где GL_LIGHTi предопрелено в
файле gl.h следующим образом:
/* LightName */
#define GL_LIGHT0
#define GL_LIGHT1
#define GL_LIGHT2
#define GL_LIGHT3
#define GL_LIGHT4
#define GL_LIGHT5
#define GL_LIGHT6
#define GL_LIGHT7
0x4000
0x4001
0x4002
0x4003
0x4004
0x4005
0x4006
0x4007
Второй способ - GL_LIGHT0 + i, где i номер лампы. Такой способ используется, когда вам надо в цикле изменять параметры ламп. Второй аргумент
определяет имя параметра, а третий - его значение. Я здесь не буду перечислять
всевозможные параметры и их допустимые значения, для этого есть справочник
и MSDN. Я покажу и прокомментирую лишь небольшой пример, использующий три лампы. Для начала, давайте разберем шаблонный пример. С помощью
следующих функций разрешаем освещение и включаем нулевую лампу.
27
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
Массивы pos и dir содержат координаты местоположения лампы и
направления, куда она светит. Массив dir содержит три координаты - x,y,z.
Массив pos – четыре. Если значение четвертой компоненты равно нулю, то источник считается бесконечно удалённым и ослабления света при удалении от
источника не происходит.
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
РАЗДЕЛ 4. Словарь терминов (глоссарий)
Программирование в среде Visual Studio 2005 C++
Главное меню
Интерфейс
Класс
Контекстное меню
Контрольный элемент
графический список
группирующая рамка
кнопка
комбинированный список
наборный счётчик
переключатель
ползунок
поле ввода
полоса прокрутки
рисунок
статический текст
флажок
ActiveX-элемент
Панель инструментов
Событие класса
Строка состояния
Графический стандарт OpenGL
Лампа
Материал
Плоскость отсечения
Примитивы
геометрические
точки
линии
треугольники
многоугольники
пространственные
28
конус
куб
сфера
тор
цилиндр
чайник
Текстура
Текстурирование
РАЗДЕЛ 5. Практикум по решению задач (практических ситуаций) по темам лекций (одна из составляющих частей итоговой государственной аттестации)
Программирование в среде Visual Studio 2005 C++
Задание 1.1. Изменить заголовок «Untitled» («Безымянный») в левом верхнем углу
окна приложения.
Решение.
1. Перейдите на вкладку Resource View окна проектов, раскройте список String Table и
дважды щёлкните левой кнопкой мыши строку abc_String_Table. Перед Вами открылась
строковая таблица редактора ресурсов.
2. Щелкните правой кнопкой мыши в любом месте этой таблицы и выберите команду
New String. В таблице появилась новая строка с идентификатором IDS_STRING1. Щелкнув
правой кнопкой мыши на этой строке, откройте окно её свойств и заполните его так, как показано на рисунке.
Строковый ресурс AFX_IDS_UNTITLED используется для задания имени приложения в левом верхнем углу. Закройте окно свойств.
3. Сохраните файл ресурсов на диске и закройте окно редактора ресурсов.
Соберите приложение и запустите его на выполнение. Убедитесь, что заголовок изменился.
Задание 1.2. Расположить диалоговое окно в центре экрана.
29
Решение.
Чтобы расположить диалоговое окно в центре экрана, в файле MyPr02View.cpp добавьте в конец функции инициализации OnInitialUpdate строку:
GetParent()->CenterWindow();
Соберите приложение и запустите его на выполнение. Убедитесь, что окно приложения расположено в центре экрана.
Задание 1.3. Наложить растровое изображение на управляющий элемент «рисунок».
Решение.
Рассмотрим процедуру наложения растрового изображения на управляющий элемент.
Напомню, что мы уже связали с управляющим элементом Picture переменную m_bPicture.
1. Готовую картинку с изображением эллипса загрузим из файла: VisualC_Part01\FilesForStud\ Ellipse.bmp.
Скопируйте этот файл в свою папку MyPr04.
Перейдите на вкладку Resource View, щёлкните правой кнопкой мыши в любом месте
этой вкладки и в открывшемся контекстном меню выберите команду Add Resource.
Перед Вами открылось одноимённое окно. Выберите в нём пункт Bitmap (Рисунок) и
щёлкните кнопку Import, после чего выберите файл Ellipse.bmp.
2. Не закрывая картинку, выполните цепочку команд: вкладка ResourceView > Bitmap
> щелкнуть правой кнопкой мыши IDB_BITMAP1, выбрать Properties и переименовать идентификатор в IDB_ELLIPSE. Закройте окно свойств и картинку.
3. Сохраните файл ресурсов на диске.
4. Добавьте в файл MyPr04Dialog.h объявление закрытой переменной:
private:
CBitmap m_bEllipse;
5. Добавьте функцию инициализации OnInitDialog: вкладка Class View > класс
CMyPr04Dialog > окно свойств (правая кнопка мыши) > кнопка Overrides > OnInitDialog.
Перед оператором return вставьте в текст функции OnInitDialog следующий код:
// Загрузить в переменную m_bEllipse рисунок с идентификатором IDB_ELLIPSE
m_bEllipse.LoadBitmap(IDB_ELLIPSE);
// На основе этого рисунка создать структуру hBitmap типа HBITMAP
HBITMAP hBitmap=(HBITMAP) m_bEllipse.GetSafeHandle();
// К элементу управления «Рисунок» присоединить структуру hBitmap
m_bPicture.SetBitmap(hBitmap);
6. Соберите и запустите Ваше приложение. Открыв диалоговое окно, Вы можете полюбоваться рисунком эллипса на желтом фоне.
Задание 1.4. Наложить на кнопку пиктограмму.
Решение.
30
Наложим на кнопку «Нарисовать» картинку, хранящуюся в файле с расширением ico
(так называемую иконку). Напомню, что ранее мы связали с этой кнопкой переменную
m_bPaint.
1. Откройте редактор диалогового окна и в свойствах кнопки «Нарисовать» установите свойство Icon.
2. Скопируйте в Вашу папку MyPr07 файл: VisualC_Part01\FilesForStud\Brush.ico.
Перейдите на вкладку Resource View, щёлкните правой кнопкой мыши строку Icon и
в открывшемся контекстном меню выберите команду Add Resource.
Перед Вами открылось одноимённое окно. Выберите в нём пункт Icon («Иконка») и
щёлкните кнопку Import, после чего выберите файл Brush.ico.
Если картинка Вам не понравилась, можете нарисовать свою.
3. Не закрывая картинку, щелкните правой кнопкой мыши идентификатор IDI_ICON1
на вкладке Resource View, выберите команду Properties и в окне свойств переименуйте идентификатор ID в IDI_ICON_BRUSH.
4. Закройте картинку и сохраните файл ресурсов на диске.
5. В файле MyPr07View.cpp добавьте в конец функции OnInitialUpdate строки:
// Загрузить в структуру m_iButton (это переменная типа HICON)
// "иконку" с идентификатором IDI_ICON_BRUSH
HICON m_iButton = AfxGetApp()->LoadIcon(IDI_ICON_BRUSH);
// К кнопке "Нарисовать" присоединить структуру hBitmap
m_bPaint.SetIcon(m_iButton);
6. Соберите приложение и запустите его на выполнение. Убедитесь, что изображение
на кнопке появилось. При нанесении растрового изображения на кнопку её размер менялся
автоматически. При нанесении пиктограммы размер кнопки придётся поменять вручную.
Задание 1.5. Подключить файл справочной системы.
Решение.
Рассмотрим, как подключить уже готовый файл.
1. Скопируйте из папки VisualC_Part01\FilesForStud\ в свой директорий MyPr07 файл
LB_07_HLP.HLP.
2. Создадим процедуру  обработчик команды «Помощь». Это будет обработчик сообщения COMMAND для идентификатора ID_HELP.
2.1. Откроем редактор ресурса «Главное меню»: ResourceView > Menu > дважды
щелкнуть левой кнопкой мыши IDR_MAINFRAME.
2.2. Добавим обработчик: щёлкните правой кнопкой мыши ячейку «Помощь» и в открывшемся контекстном меню выберите команду Add Event Handler (Добавить Событие).
В окне Event Handler Wizard выберите класс CMyPr07View, убедитесь, что в списке
Message type указано сообщение COMMAND и нажмите кнопку Add and Edit (Добавить и
Редактировать).
В текст функции OnHelp внесите строку:
::WinHelp(GetSafeHwnd(), "LB_07_HLP.HLP", HELP_FINDER, 0);
31
3. Соберите приложение и запустите его на выполнение. Убедитесь, что файл справочной системы можно открыть как из главного меню, так и с панели инструментов.
Задачи для самостоятельного решения
Задание 1.6. Объявите вещественную переменную MyVar, задайте её начальное значение равным MyVar = 1,05. Пусть при нажатии клавиши значение этой переменной увеличивается вдвое, а при щелчке правой кнопки мыши функция AfxMessageBox выводит её значение на экран.
Задание 1.7. Предусмотрите в своём приложении очистку экрана
Указание
1. К пункту Главного меню Paint добавьте команду Clear Screen и присвойте ей идентификатор ID_CLEARSCREEN.
2. На Панель инструментов поместите новую кнопку с тем же идентификатором.
3. Напишите обработчик сообщения COMMAND для идентификатора
ID_CLEARSCREEN, общий для новой кнопки и команды меню.
4. Напишите обработчик сообщения UPDATE COMMAND UI для идентификатора
ID_CLEARSCREEN, общий для новой кнопки и команды меню. Этот обработчик должен делать команду и кнопку недоступными в том случае, если экран чист.
Графический стандарт OpenGL
Задание 2.1. Реализовать процедуру, рисующую три сферы разного цвета.
Решение. Вставьте в текст функции display следующий код:
glPushMatrix();
// сохраняем текущие координаты
glTranslated(1.4,0,0);
// сдвигаемся по оси Х на
1.4
glColor3d(0,1,0);
auxSolidSphere(0.5); // рисуем сферу в (1.4,0,0)
// в абсолютных координатах
glTranslated(1,0,0);
glColor3d(0,0,1);
auxSolidSphere(0.3);
glPopMatrix();
динат
// еще раз сдвигаемся
// возвращаемся к старой системе коор-
glColor3d(1,0,0);
auxSolidSphere(0.75); // рисуем сферу в точке (0,0,0)
// в абсолютных координатах
32
Задание 2.2. «Срежьте» часть сферы с помощью плоскости отсечения.
Решение.
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();
Задание 2.3. Добавьте в своё приложение спецэффект «туман». Предусмотрите изменение плотности тумана с помощью клавиш клавиатуры.
Решение.
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);
}
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);
33
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);
}
}
Задание 2.4. Изобразить объект, получающийся в результате булевой операции: «куб
минус сфера»
Решение.
void CALLBACK display(void)
{
// очищаем все буферы
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
// разрешаем тест трафарета
glEnable(GL_STENCIL_TEST);
// рисуем куб и заполняем буффер трафарета единицами
// в том месте, где рисуется куб
34
glStencilFunc(GL_ALWAYS, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
auxSolidCube(2.5);
// заполняем буффер трафарета двойками
// в том месте, где сфера закрывает куб
glStencilFunc(GL_ALWAYS, 2, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
auxSolidSphere(1.5);
// очищаем буфферы цвета и глубины
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glStencilFunc(GL_EQUAL, 1, 255);
glColor3d(1,1,1);
auxSolidCube(2.5);
// вращаем сцену
glRotated(3, 1,0,0);
glRotated(5, 0,1,0);
glRotated(7, 0,0,1);
auxSwapBuffers();
}
Задачи для самостоятельного решения
Задание 2.5. Используя функции glTranslated и glRotate, нарисуйте снеговика.
Три сферы, шапка - конус, нос - тоже конус, глаза - сфера, рот можно сделать квадратным glBox.
Задание 2.6. «Научите» Вашего снеговика передвигаться вдоль осей OX и OY с помощью клавиатуры, а также, используя плоскость отсечения, переделайте его шляпу из конуса в ведро.
Раздел 6. Изменения в рабочей программе, которые произошли после
утверждения программы.
Характер
изменений в
программе
Номер и дата
протокола заседания кафедры,
на котором было
принято данное
решение
Подпись заведующего кафедрой,
утверждающего
внесенное изменение
Подпись декана факультета (проректора
по учебной работе),
утверждающего данное изменение
35
Раздел 7. Учебные занятия по дисциплине ведут:
Ф.И.О., ученое
звание и степень
преподавателя
Шуньгина И.В.,
ассистент
Учебный Факультет
год
2010-2011 ФМОИП
Специальность
Прикладная математика и информатика
Download