ВВЕДЕНИЕ
Бурный рост спроса на программные продукты во всем мире, связанный, в первую очередь, с развитием и распространением Интернета и систем электронной торговли и бизнеса, а также с внедрением новых поколений вычислительной техники и передовых достижений компьютерной графики, приводит к росту спроса на программные продукты, которые с максимальной функциональность
Целью данного курсового проекта является изучение структуры параметризирован
В программе реализована параллельное аксонометрическо
Данная программа является реализацией основных операций, необходимых для работы с объемными изображениями. Всё это очень важно для познания методов представления 3D-графики и качественного и эффективного использования её в графическом и геометрическом моделировании в информационных системах.
ПОСТАНОВКА ЗАДАЧИ
Целью данного курсового проекта является изучение структуры параметризирован
Систему трехмерного графического моделирования должна обладать следующей функциональность
— реализация заданного множества параметризирован
– призма;
– цилиндр;
– додекаэдр;
– икосаэдр;
– пирамида с пятиугольным основанием;
– усеченная пирамида с пятиугольным основанием.;
– октаэдр;
— реализация сложного объекта – журнальный столик (см. рис. А1);
- разработка структуры объектов;
- движения по заданной траектории заданного набора параметризирован
- реализация типичных операций управления «камерой» при визуализации и элементов управления объектом;
- возможность редактирования и манипулирования объектами в графической БД;
- разработка системы помощи.
- вызов всех функций реализуется в главном меню и продублирован в виде кнопок;
— загрузка и сохранения всех параметров сцены в файл данных;
— корректный выход из программы (без зависаний приложения);
— реализация планировки сцены (визуализация координатных осей);
— реализация заданного расположения и направления камеры;
— выбор типа проецирования;
— изменение размеров сцены;
- реализация всех аффинных преобразований для объекта с возможностью редактирования параметров: перенос, масштабирование, вращение вокруг каждой из осей, сдвиг, отражение вокруг каждой из осей.
Данная программа является реализацией основных операций, необходимых для работы с объемными изображениями. Всё это очень важно для познания методов представления 3D-графики и качественного и эффективного использования её в графическом и геометрическом моделировании в информационных системах.
1 ОБЗОР И СРАВНИТЕЛЬНЫЙ АНАЛИЗ ГРАФИЧЕСКИХ БИБЛИОТЕК И ОБОСНОВАНИЯ ИСПОЛЬЗОВАНИЯ БИБЛИОТЕКИ OpenGL
1.1 Обзор графических библиотек и обоснования использования библиотек OpenGl
На данный момент в Windows существуют два стандарта для работы с трехмерной графикой: OpenGl, являющийся стандартом де-факто для всех рабочих станций, и Direct3D-стандар
1.1.1 Библиотека OpenGl
Для реализации программных модулей была использована интегрированная среда разработки Visual C++ 6.0 корпорации Microsoft. Для реализации графических моделей выбор был остановлен на библиотеке OpenGl, потому что она имеет ряд следующих преимуществ.
OpenGL — Open Graphics Library, открытая графическая библиотека. Термин «открытый» — означает независимый от производителей. Имеется спецификация стандарт) на OpenGL, где все четко задокументирован
1.1.2 Стандартная библиотека C++
В Visual C++ используется реализация стандартной библиотеки C++, основанная на стандарте для языка C++ и библиотеки, ратифицированной Американским национальным институтом стандартов (ANSI) и Организацией Международных Стандартов (ISO).
Начиная с его разработки доктором Бьярном Страуструпом в 80-х годах, язык C++ широко использовался профессиональным
Стандартизация улучшает мобильность и стабильность. Использование Стандартной Библиотеки C++ позволяет формировать надежные приложения быстрее и обслуживать их с меньшими затратами и усилиями.
1.2 Программирование в Visual C++
1.2.1 Интегрированная среда разработки (IDE)
После запуска Visual C++, мы немедленно попадаем в интегрированную среду разработки, также называемую (IDE). Эта среда обеспечивает все инструментальные средства, которые нужны для проектирования, разработки, тестирования, и отладки приложений.
Среда разработки Visual C++ включает:
- визуальный проектировщик ресурсов (visual resource designer);
- менеджер классов (Class Mahager);
- палитру компонентов (Component palette);
- организатор проекта (Project Manager);
- редактор исходного текста (source code editor);
- отладчик (debugger).
Вы можете свободно двигаться от визуального представления объекта (в проектировщике ресурсов), к менеджеру классов, чтобы редактировать начальное состояние объекта; к редактору исходного текста, чтобы редактировать логику выполнения. Изменение свойств, связанных с кодом, например имени обработчика события, в менеджере классов автоматически изменяет соответствующий исходный текст. Кроме того, изменения в исходном тексте, типа переименования обработчика события в объявлении класса, немедленно отражается в менеджере классов.
1.2.2 Проектирование приложений
Visual C++ включает все инструментальные средства, необходимые для начала разработки приложения:
- пустое окно, для проектирования пользовательског
- обширная библиотека классов с объектами многократного использования;
- менеджер классов для просмотра и изменения свойств классов;
- редактор кода, который обеспечивает прямой доступ к основному тексту программы;
- организатор проекта для управления файлами, которые составляют один или больше проектов;
- много других инструментальных средств типа редактора изображений на панели инструментов и редактора меню;
Можно использовать Visual C++ для проектирования 32-разрядного Windows-приложен
1.2.3 Библиотека классов MFC
Библиотека классов MFC (Microsoft Foundation Classes) основана на модели свойства/методы/
2 АНАЛИЗ СТРУКТУРЫ ПРОГРАММЫ И ГРАФИЧЕСКИХ ГЕОМЕТРИЧЕСКИХ МЕТОДОВ
2.1 Анализ структуры программы
2.1.1 Структура приложения
В данном программном продукте приложение реализовано на языке Visual C++ 6.0 и построено по принципам обычного приложения с однодокументным интерфейсом. Приложение построено на основе архитектуры документ-предста
Данный программный продукт построен по принципу интерактивной работы с пользователем — приложение предоставляет панель меню и отдельную кнопочную панель, которые, по соответствующим действиям пользователя, вызывают соответствующие обработчики, функции.
Данная структура программы имеет ряд преимуществ:
- архитектура документ-предста
- блоки диалога позволяют постоянно отображать (и изменять) полную информацию об объектах документа;
- панели инструментов предоставляют удобный интерфейс для настройки приложения и объектов документа;
- сохранение и восстановление данных документа по методу сериализации позволяет быстро и эффективно (в без избыточном формате) связать данные документа с файлом.
Таким образом, на данный момент программа построена по одному из наиболее оптимальных способов, соединив в себе наиболее сильные методы, предоставляемые библиотекой MFC.
2.1.2 Структура графических объектов и камеры
Каждый графический объект и камера реализованы отдельными классами и содержат специфические для каждого из них свойства, методы и переменные:
- dcGObject, класс базового объекта, хранящего список вершин и граней объекта, описание свойств материала, указатель на карту текстуры;
- dcGScene, класс сцены, хранит список объектов сцены и предоставляет функции для работы со сценой;
- dcGFactory, класс «фабрики» объектов, содержит функции создания разнообразных объектов сцены;
- dcGCamera, класс камеры сцены, содержит описание параметров камеры;
- dcGLight, класс источника света, содержит параметры светового потока;
Для вывода графической информации используются возможности библиотеки OpenGL. Все функции отображения сцены реализованы через функции библиотеки OpenGL.
2.2 Системы координат
2.2.1 Декартовая система координат
Если через точку пространства проведены три попарно перпендикулярные прямые, на каждой из них выбрано направление и выбрана единица измерения отрезков, то это значит, что задана декартовая система координат в пространстве. Прямые с выбранными на них направлениями называются осями координат, а их общая точка – началом координат. Эта система устанавливает взаимооднозначно
M(x,y,z)
Рисунок 2.1 – Декартовая система координат
Различают правостороннюю и левостороннюю системы координат. Правосторонняя системой координат OXYZ – это такая система, в которой вращение относительно оси z происходит от оси x к оси y (против часовой стрелки).
Левостороняя – это система координат, в которой вращение относительно оси z происходит от оси y к оси x (по часовой стрелке).
В данном курсовом проекте использовалась правосторонняя декартовая система координат.
2.2.2 Векторная система координат
Векторная система координат устанавливает взаимооднозначно
Вектор AB c координатами (x,y,z).
Рисунок 2.2 – Векторная система координат
2.2.3. Аффинная система координат
Аффинная система координат устанавливает взаимооднозначно
2.2.4 Однородные координаты точки
В общем случае любая точка (х1, х2, х3, …,хN) в n-мерном пространстве записывается как точка (wх1, wх2, wх3, …wхN, w) в (n+1)–мерном пространстве, где w – любое ненулевое вещественное число. Эта группа из n+1чисел определяет однородные координаты исходной точки в n-мерном пространстве. Однородные координаты возникли из-за необходимости обратного преобразования из n-мерного пространства в (n+1)-мерное пространство. Точка A(5,7,4) в трехмерном пространстве, например, может быть записана в однородных координатах как А’(15,21,12,3) или как A”(500, 700,400,100) и так далее.
Пусть M – произвольная точка пространства с координатами x, y, z, тогда однородными координатами называется любая четвёрка одновременно неравных нулю чисел x1, x2, x3, x4, связанных с заданными x, y, z следующими соотношениями:
(2.1)
2.3 Аффинные преобразования
Аффинные преобразования – это комбинация линейных преобразований, при которых параллельные линии переходят в параллельные, скрещивающиеся в скрещивающиеся, отношение отрезко7в на параллельных прямых сохраняются.
Среди аффинных преобразований различают: перенос, масштабирование, поворот, сдвиг, отражение. При проведении расчетов полезным является использование однородных координат, так как в обычных координатах используются громоздкие вычисления (сложение, умножение координат), а в однородных координатах вычисления упрощаются (матрицы перемножаются). Но основной целью введения однородных координат является их несомненное удобство в применении к геометрическим преобразованиям. Для упрощения вычислений в задачах компьютерной графики формулы преобразований представляют в виде матриц.
При помощи четверок однородных координат и матриц четвертого порядка можно описать любое аффинное преобразование плоскости.
P’=P*M (2.2)
Рассмотрим аффинные преобразования, которые используются в нашей системе (оси абсцисс Ox, ординат Oy и аппликат Oz показаны на рисунке 2.2).
Матрица вращения вокруг оси абсцисс на угол :
(2.3)
Матрица вращения вокруг оси ординат на угол :
(2.4)
Матрица вращения вокруг оси аппликат на угол :
(2.5)
Вращение вокруг оси аппликат на угол показано на рисунке 2.3.
Рисунок 2.3 – Вращение вокруг оси аппликат
Матрица растяжения (сжатия):
, (2.6)
где
> 1 — коэффициент растяжения вдоль оси абсцисс;
> 1 — коэффициент растяжения вдоль оси ординат;
> 1 — коэффициент растяжения вдоль оси аппликат.
Если 0<<1, 0<<1, 0<<1, то , , — коэффициенты сжатия вдоль осей абсцисс, ординат, аппликат соответственно.
Матрица переноса (вектор переноса (,,))
(2.7)
Перенос точки Р в точку Р’ показан на рисунке 2.4.
Рисунок 2.4 — Перенос
Матрица отражения относительно плоскости XОY:
(2.8)
Отражение относительно плоскости XОY показано на рисунке 2.5.
Рисунок 2.5 – Отражение относительно плоскости
Матрица отражения относительно плоскости XОZ:
(2.9)
Матрица отражения относительно плоскости YОZ:
(2.10)
2.4 Проецирование: параллельное и центральное
Изображение объектов на картинной плоскости связано с ещё одной геометрической операцией – проецированием. В компьютерной графике используется несколько различных видов проецирования. На практике наиболее употребимые – параллельное и центральное.
Для получения проекции объекта на картинную плоскость необходимо провести через каждую его точку прямую из заданного проектирующего пучка и найти координаты точки пересечения этой прямой с плоскостью изображения. В случае центрального проецирования все прямые исходят из одной точки – центра собственного пучка. При параллельном проецировании центр (несобственного) пучка считается лежащим на бесконечности (рисунок 2.6).
Рисунок 2.6 – Проектирующие пучки
В данном курсовом проекте реализовано изометрическое центральное проецирование, которое задается при помощи камер.
Изометрическая проекция получается комбинацией поворотов, за которой следует параллельное проецирование. При повороте на угол R относительно оси ординат, на угол Q вокруг оси абсцисс и последующего проектирования вдоль оси аппликат формируется матрица:
(2.11)
Построение центральных проекций организуется следущим образом. Если центр проецирования лежит на оси аппликат в точке С(0,0,с) и плоскость проецирования совпадает с координатной плоскостью XY, то через произвольную точку пространства М(x,y,z) и точку C можно провести прямую и записать соответствующее параметрическое уравнение.
X’=xt, Y’=yt, Z’=c+(z-c)t
Найдя координаты точки пересечения построенной прямой с плоскостью XY. Из условия Z’=0 получается, что
, следовательно ,
В данной системе используется также ортографическое проецирование. При ортографической проекции картинная плоскость совпадает с одной из координатных плоскостей или параллельна ей. Матрица проецирования вдоль оси X на плоскость YZ имеет вид:
(2.12)
При переходе к однородным координатам получается матрица следующего вида:
(2.13)
Перспективная проекция получается путем перспективного преобразования и проецирования на некоторую двумерную плоскость наблюдения. Предположим, что центр проецирования лежит на оси Z в точке C(0,0,c) и плоскость проецирования совпадает с координатной плоскостью XY (рисунок 2.7), тогда соответствующая матрица будет иметь вид:
(2.12)
Рисунок 2.7 – Перспективная проекция
2.5 Управление камерой
2.5.1. Мировая и локальная системы координат
Мировая система координат – общая система координат, заданная началом координат и тремя ортонормированны
Локальная система координат вводит свою точку отсчета и направление координатных осей. В мировой системе координат можно описать бесконечное множество локальных систем координат.
2.5.2 Камера сцены
Совокупность объектов мировой системы координат определяют сцену. К объектам сцены относятся как трехмерные объекты, так и камеры, задающие видовые операции. Камера управляет проецированием.
Каждая камера задается следующими параметрами:
— положение в мировой системе координат;
— направление камеры (точнее, точкой, в которую направлена эта камера);
— угол зрения камеры;
— угол поворота относительно главной оптической оси.
Камера показана на рисунке 2.8.
Главная оптическая ось направлена по нормали к экрану.
Каждая локальная система координат может быть представлена в мировой системе координат положением начала координат и направлением x, y (достаточно направление двух осей).
Рисунок 2.8 – Камера
2.5.3Типичные преобразования камер
Камера представляет собой обычный объект, заданный в локальной системе координат, являющийся равноправным со всеми остальными объектами и определяет перспективные или параллельные проекции. Точка проецирования называется фокусом. В локальной системе координат эта точка находится на главной оптической оси.
Типичные операции управления камерой:
а) панорамирование – камера поворачивается влево-вправо. Матрица панорамирования совпадает с матрицей поворота вокруг оси OZ на некоторый угол ;
б) вертикальное панорамирование – поворот вверх-вниз. Матрица вертикального панорамирования совпадает с матрицей поворота вокруг оси OX на некоторый угол ;
в) зуммирование – изменение угла зрения или расстояния до центральной точки. При зуммировании камера остается на месте. Матрица зуммирования может быть получена путем умножения матриц двух последовательных преобразований: перспективного преобразования и проецирования на плоскость OXZ;
г) вращение камеры вокруг главной оптической оси. Матрица вращения вокруг главной оптической оси совпадает с матрицей поворота вокруг оси ординат OY’ локальной системы координат. Поворот аналогичен повороту вокруг оси ординат OZ (рисунок 2.3);
д) наезд и откат камеры – перемещение камеры вдоль главной оптической оси. В этом случае изменяется положение камеры в мировой системе координат;
е) перенос влево-вправо и вверх-вниз относительно главной оптической оси.
2.6 Алгоритм удаления невидимых граней и поверхностей
Алгоритм удаления скрытых граней, реализованный в данной курсовой работе называется алгоритмом Z-буфера или буфера глубины.
Метод z-буфера (буфера глубины) является одним из самых простых алгоритмов удаления невидимых граней и поверхностей является, где для каждого пиксела находится грань, ближайшая к нему вдоль направления проектирования.
Поставим в соответствие каждому пикселу (x,y) картинной плоскости кроме цвета c(x,y), хранящегося в видеопамяти, его расстояние до картинной плоскости вдоль направления проектирования z(x,y) (его глубину).
Массив глубин инициализируется +.
Для вывода на картинную плоскость произвольной грани она переводится в растровое представление на картинной плоскости и затем для каждого пиксела этой грани находится его глубина. В случае, если эта глубина меньше значения глубины, хранящегося в z-буфере, пиксел рисуется и его глубина заносится в z-буфер.
Весьма эффективным является совмещение растровой развертки грани с выводом в z-буфер. При этом для вычисления глубины пикселов могут применяться инкрементальные методы, требующие всего нескольких сложений на пиксел.
Грань рисуется последовательно строка за строкой; для нахождения значений используется линейная интерполяция.
Фактически метод z-буфера осуществляет поразрядную сортировку по x и y, а затем сортировку по z, требуя всего одного сравнения для каждого пиксела каждой грани.
Метод z-буфера работает исключительно в пространстве картинной плоскости и не требует никакой предварительной обработки данных. Порядок, в котором грани выводятся на экран, не играет никакой роли.
Средние временные затраты составляют O(n), где n-общее количество граней.
Одним из основных недостатков z-буфера (помимо большого объема требуемой под буфер памяти) является избыточность вычислений: осуществляется вывод всех граней вне зависимости от того видны они или нет. И если, например, данный пиксел накрывается десятью различными лицевыми гранями, то для каждого соответствующего пиксела каждой из этих десяти граней необходимо произвести расчет цвета. При использовании сложных моделей освещенности и текстур эти вычисления могут потребовать слишком больших временных затрат.
2.7 Методы постоянного закрашивания и Гуро
В большинстве случаев модели задаются набором плоских выпуклых граней. Поэтому при построении изображения естественно воспользоваться этой простотой модели. Существует три простейших метода рендеринга полигональных моделей, дающих приемлемые результаты, — метод плоского (постоянного) закрашивания, метод Гуро и метод Фонга.
Метод постоянного закрашивания самый простой из всех трех. Он заключается в том, что на грани берется произвольная точка и определяется ее освещенность, которая и принимается за освещенность всей грани.
Получающееся при этом изображение носит ярко выраженный полигональный характер – сразу видно, что модель состоит из отдельных плоских граней. Это связано с тем, что если рассматривать освещенность вдоль поверхности какого-либо объекта, то она претерпевает разрывы на границах граней.
В данном курсовом проекте был использован метод Гуро, так как он наиболее реалистично обеспечивает непрерывность освещения вдоль границ объектов. Этот метод обеспечивает непрерывность освещенности за счет использования билинейной интерполяции.
Для того, чтобы закрасить фигуры методом Гуро, производится связывание вершин с нормалями, которые получаются в результате усреднений нормалей многоугольников, пересекающихся в этой вершине.
2.8 Полигональная и проволочная модели
Трехмерные объекты могут быть отображены в двух видах: в виде проволочной или полигональной модели.
Проволочная модель в пространстве представляет собой набор точек.
Полигональная модель в пространстве представляет собой сплошное непрозрачное тело.
Данный программный продукт реализован по принципу интерактивной работы с пользователем — приложение предоставляет 6 панелей кнопок и 1 панель меню, которые, по соответствующим действиям пользователя, вызывают соответствующие обработчики, функции.
3 СОЗДАНИЕ ГРАФИЧЕСКИХ И ГЕОМЕТРИЧЕСКИХ МОДЕЛЕЙ
3.1 Методы организации и обработки информации в графической БД
Объекты сцены задаются вершинами и гранями. В каждом объекте хранится информация о количестве его вершин, и граней. В данном курсовом проекте будет реализовано параметрическое задание геометрии объектов. Грани объектов задаются тремя точками. Геометрия объектов подвергается преобразованиям проецирования для отображения в окнах проекций.
3.2 Построение цилиндра
Цилиндрической поверхностью называется поверхность, образуемая движением прямой (АВ), сохраняющей одно и то же направление и пересекающую данную (MN). Линия MN называется направляющей; прямые линии, соответствующие различным положения прямой АВ, называются образующими цилиндрической поверхности. Тело, ограниченное цилиндрической поверхностью и двумя параллельными плоскостями, называется цилиндром (рис. 3.2). Радиусом(R) цилиндра называется радиус его основания. Высотой (h), называется расстояние между плоскостями его оснований. Параметром цилиндра также является количество точек разбиения окружности основания(n). N раз проводим поворот АВ поверхности на угол и находим координаты АВ1.
АВ =(R,0,0) (начальная точка нижнего основания) Pi=Pi-1Поворотz(α) AB1=(R,0,H) (начальная точка нижнего основания) Pi΄=Pi-1΄Поворотz(α)
=(2*)\N
Параметры построения:
R – радиус основания;
h – высота цилиндра;
n – количество аппроксимаций.
Алгоритм построения. Центр локальной системы координат связываем с геометрическим центром нижнего основания цилиндра. Цилиндр описывается при помощи радиальных сегментов.
Координаты вершин нижнего основания рассчитываются следующим образом:
; (3.1)
Координаты вершин верхнего основания рассчитываются следую-щим образом:
, (3.2)
Получившиеся точки соединяют прямой линией.
Цилиндр показан на рисунке 3.3.
Рисунок 3.2 – Цилиндр
3.3 Построение призмы
Призмой (рис. 3.3) называется многогранник, у которого две грани ABC и abc (основание призмы)- равные многоугольники с соответственно параллельными сторонами, а все остальные грани (AabB, BbcC и т.д.)- параллелограммы, плоскости которых параллельны одной прямой (Aa, Bb, Cc и т.д.). Параллелограммы Abba, BCcb и т.д называются боковыми гранями. Ребрами Aa, Bb и т.д. называются боковыми. Высотой призмы называется перпендикуляр H, опущенный из любой точки одного основания на плоскость другого.
Параметры построения призмы:
R – радиус основания;
h – высота призмы;
n – количество аппроксимаций;
— угол наклона.
Алгоритм построения.
Призма описывается при помощи радиальных сегментов. Центр локальной системы координат связываем с геометрическим центром нижнего основания призмы. Координаты вершин нижнего основания рассчитываются следующим образом:
; (3.3)
Координаты вершин верхнего основания рассчитываются следующим образом:
, (3.4)
Координаты верхнего и нижнего основания соединяются между собой прямыми линиями.
Призма показана на рисунке 3.3.
Рисунок 3.3 — Призма
3.4 Построение пирамиды с пятиугольным основанием
Пирамидой (рис. 3.4) называется многогранник, у которого одна грань — основание пирамиды — многоугольник (ABCDE), а остальные -боковые грани — треугольники с общей вершиной S, называется вершиной пирамиды. Перпендикуляр SO, опущенный из вершины на основание, называется высотой пирамиды.
Центр локальной системы координат связываем с геометрическим центром пирамиды. Пирамида описывается при помощи радиальных сегментов.
Координаты вершин основания рассчитываются следующим образом:
; (3.5)
где R – радиус основания;
h – высота пирамиды;
n – количество аппроксимаций.
После построения основания, строим вершину , а затем соединяем вершины линиями.
Пирамида с пятиугольным основанием представлена на рисунке 3.4.
Рисунок 3.4 — Пирамида с пятиугольным основанием
3.5 Построение усеченной пирамиды с пятиугольным основанием
Если в пирамиде провести сечение abcde, параллельно основанию ABCDE, то тело ограниченное этим сечение, основанием и заключенной между ними боковой поверхности пирамиды, называется усеченной пирамидой (рис.3.5). Параллельные грани усеченной пирамиды (ABCDE и abcde) называются ее основаниями, расстояния между ними (ОО1)
Центр локальной системы координат связываем с геометрическим центром пирамиды. Пирамида описывается при помощи радиальных сегментов. Координаты вершин нижнего основания рассчитываются следующим образом:
; (3.6)
Координаты вершин верхнего основания рассчитываются следующим образом:
, (3.7)
Усеченная пирамида с пятиугольным основанием показана на рисунке 3.5.
Рисунок 3.5– Усеченная пирамида с пятиугольным основанием
3.6 Октаэдр
Центр локальной системы координат связываем с геометрическим центром октаэдра. Для построения октаэдра используется длина его радиуса R. Алгоритм построения геометрии октаэдра основан на том факте, что все его грани представляют собой правильные треугольники.
Количество вершин октаэдра равно 6.
Координаты вершин:
V1 (0;0;R);
V2 (R;0;0);
V3 (0;R;0);
V4 (-R;0;0);
V5 (0;-R;0);
V6 (0;0;-R).
Получившиеся вершины соединяем линиями.
Октаэдр показан на рисунке 3.6.
Рисунок 3.6 — Октаэдр
3.7 Икосаэдр
Центр локальной системы координат связываем с геометрическим центром икосаэдра. Параметры построения: длина стороны икосаэдра – R2. Алгоритм построения:
1) строим две окружности единичного радиуса, перпендикулярные оси z, на высоте 1/2, как показано на рисунке 3.7;
2) каждую окружность разбиваем на 5 равных сегментов, точки соединяем между собой;
3) вращаясь против часовой стрелки на угол = 2/5 выбираем точки икосаэдра
P0 (0; 0; 5/2); P0’(0; 0; — 5/2);
P1 (1/2; 0; -1/2); P1’ (-1/2; 0; -1/2);
Pi = Pi-1*Поворот(2/5); Pi’ = Pi-1’*Поворот(2/5);
Матрица поворота
4) соединяем вершины линиями.
6
7 5
8 4
9 3
1 10 2
Рисунок 3.7 – Рассечение цилиндра
3.8 Построение додекаэдра
Для построения додекаэдра (рис. 3.8) используется длина его ребра. Алгоритм построения геометрии додекаэдра основан на том факте, что все его грани представляют собой правильные пятиугольники. В каждой вершине сходится по три ребра.
Путем простейших аффинных преобразований добиваемся, чтобы объект находился в такой системе координат (локальной), как показано на рисунке 4.3.
Параметры построения: длина стороны додекаэдра – R2. Алгоритм построения:
1) строим две окружности единичного радиуса, перпендикулярные оси z, на высоте 1/2;
2) каждую окружность разбиваем на 5 равных сегментов, точки соединяем между собой;
3) вращаясь против часовой стрелки на угол = 2/5 выбираем точки икосаэдра
P0 (0; 0; 5/2); P0’(0; 0; — 5/2);
P1 (1/2; 0; -1/2); P1’ (-1/2; 0; -1/2);
Pi = Pi-1*Поворот(2/5); Pi’ = Pi-1’*Поворот(2/5);
Матрица поворота
4) находим центры тяжестей граней икосаэдра – они являются вершинами додекаэдра.
5) соединяем вершины линиями.
Количество вершин додекаэдра равно 20.
Рисунок 3.8 — Додекаэдр
4 МАТЕМАТИЧЕСКАЯ МОДЕЛЬ СЛОЖНОГО ОБЪЕКТА
Центр локальной системы координат связываем с геометрическим центром сложного объекта (журнального столика). Алгоритм построения журнального столика:
1. Построение журнального столика начинаем с построения ножек столика (3 призм) –noga1, noga2, noga3. Рассчитаем параметры 1-ой призмы noga1. Ее параметры (R, H, Angle,Seg), S, P.
Transformations
Translate(перено
Rotated(поворот)
Scale(масштабиро
Noga2
Translate(перено
Rotated(поворот)
Scale(масштабиро
Noga3
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение ног(призм) показано на рисунке 4.1
Рисунок 4.1- Построение призм в журнальном столике
Получается, что три призмы имеют одно общее, верхнее, основание. Серединой этого основания будет точка (x0;y0;z0). В середине верхнего основания расположен икосаэдр с радиусом Rц.
2. Построение икосаэдра (ico)
Transformations
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение икосаэдра в журнальном столике показано на рисунке 4.2
Рисунок 4.2-Построение икосаэдра в журнальном столике
3. В качестве опоры столика использован цилиндр высотой Hц, радиусом Rц, сегментацией Seg (stoika).
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение цилиндра в журнальном столике показано на рисунке 4.3
Рисунок 4.3- Построение цилиндра в журнальном столике
4. Декоративный элемент опоры – октаэдр радиусом R=Rц, перемещенный по оси Oz(dec).
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение октаэдра в журнальном столике показано на рисунке 4.4
Рисунок 4.4- Построение октаэдра в журнальном столике
5. Вверху опоры расположена усечённая пятиугольная пирамида высотой Hуп, нижним радиусом Rн=Rц, верхним радиусом Rв>Rц. Перемещение по оси Oz(tp).
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение усеченной пятиугольной пирамиды в журнальном столике показано на рисунке 4.5
Рисунок 4.5- Построение усеченной пятиугольной пирамиды
6. Поверхностью стола служит цилиндр высотой Нц2, радиусом Rц2, сегментация 17*Seg(stol).
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение цилиндра в журнальном столике показано на рисунке 4.6
Рисунок 4.6- Построение цилиндра в журнальном столике
7. Декоративный элемент выполнен из пирамиды и додекаэдра.
Пятиугольная пирамида высотой Hп, радиусом Rп
Transformations
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение додекаэдра в журнальном столике показано на рисунке 4.7
Рисунок 4.7- Построение додекаэдра в журнальном столике
8. Декоративный элемент выполнен из пятигранной пирамиды радиусом R
Transformations
Translate(перено
Rotated(поворот)
Scale(масштабиро
Построение пятигранной пирамиды в журнальном столике показано на рисунке 4.8
Рисунок 4.8- Построение пятигранной пирамиды в журнальном столике
Построим матрицы преобразований для каждого простого объекта в журнальном столике.
Для призмы Noga1
(4.1)
Для призмы Noga2
(4.2)
Для призмы Noga3
(4.3)
Построение матрицы для икосаэдра:
Построение матрицы для цилиндра, стойки журнального столика:
Построение декоративного элемента опоры – октаэдр, его матрица выглядит следующим образом:
Вверху опоры расположена усечённая пятиугольная пирамида высотой, ее матрица выглядит следующим образом:
Поверхностью стола служит цилиндр, его матрица:
Декоративный элемент выполнен из пирамиды
Декоративный элемент выполнен из додекаэдра
5 ОПИСАНИЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
5.1 Описание основных структур данных и классов системы
5.1.1 Описание основных структур данных и классов объектов
В данной программе для визуализации объектов реального мира были созданы параметризирован
Были использованы следующие векторы:
- Vertex – однородные координаты точки в пространстве;
- Face – грань, содержит три номера вершин.
Для отображения трехмерных объектов и сцен были реализованы следующие классы:
- dcGObject, класс базового объекта, хранящего список вершин и граней объекта, описание свойств материала;
- dcGScene, класс сцены, хранит список объектов сцены и предоставляет функции для работы со сценой;
- dcGFactory, класс «фабрики» объектов, содержит функции создания разнообразных объектов сцены;
- dcGCamera, класс камеры сцены, содержит описание параметров камеры;
- dcGLight, класс источника света, содержит параметры светового потока;
Для вывода графической информации используются возможности библиотеки OpenGL. Все функции отображения сцены реализованы через функции библиотеки OpenGL.
Схему взаимодействия классов графической библиотеки и внешних объектов можно изобразить следующим образом:
Рисунок 5.1 — Схема взаимодействия классов графического модуля
Программа при помощи командного языка оформляет обращение к сцене на создание или трансформацию объекта. Сцена рассматривает обращение и если это обращение о создании объекта, то создается пустой объект и отправляется запрос о создании уже определенного объекта в фабрику объектов (в качестве аргументов запрос содержит указатель на пустой объект и тип требуемого объекта). Если обращение содержит запрос о трансформации, то производится поиск требуемого объекта и его последующая трансформация.
Также обращение может содержать команды загрузки файла скрипта.
5.2 Описание классов
5.2.2 Описание класса базового объекта сцены
Все параметрические объекты системы представлены классами, которые наследуют свойства базового класса dcGObject :
class dcGObject
{
public:
dcGObject();
dcGObject(dcGObj
virtual ~dcGObject();
CString m_sObjName;
BOOL IsVis;
// Геометрия
GLfloat *vertex;
GLint *faces;
GLubyte color[3];
GLubyte *mask;
int m_prop[3];
GLfloat px,py,pz;
GLfloat dx,dy,dz, rx,ry,rz, sx,sy,sz;
// Материал
GLubyte hasMaterial;
GLfloat ambient [4], diffuse [4], specular[4];
GLfloat shininess;
// методы
void Draw(UCHAR mode=0,LPVOID pScene=0);
void ResetProp(char bMatTrans = 1); // сброс свойств
void RemoveArrays(); // очистка содержимого массивов
void ComplexObj(); // создание составного объекта
void SaveArrays(const char *sFilename);
void operator=(dcGObj
}
Таблица 5.1 – Атрибуты класса
Тип |
Имя |
Описание |
Cstring |
m_sObjName |
Имя объекта |
BOOL |
IsVis |
Свойство «видимый ли объект?» |
GLfloat* |
Vertex |
массив координат вершин объекта |
GLint* |
Faces |
массив граней объекта |
GLubyte[3] |
color |
цвет объекта |
GLubyte* |
mask |
маска видимости граней |
int[3] |
m_prop |
число вершин, граней, размер маски |
Glfloat |
px,py,pz |
координаты точки привязки |
Glfloat |
dx,dy,dz |
параметры трансформации переноса |
Glfloat |
rx,ry,rz |
параметры трансформации поворота |
Glfloat |
sx,sy,sz |
параметры трансформации масштаба |
GLfloat[4] |
ambient |
параметры света объекта (в тени) |
GLfloat[4] |
diffuse |
параметры света рассеивания |
GLfloat[4] |
specular |
параметры цвета отражения |
Glfloat |
shininess |
коэффициент отражения |
Glubyte |
hasMaterial |
свойство «материал применён» |
dcGobject* |
m_aObject |
прикрепленные объекты |
dcGObject(), dcGObject(dcGObj
~dcGObject() – деструктор объекта.
Draw(UCHAR mode,LPVOID pScene) – функция рисования объекта. Параметр mode задает способ отображения объекта в сцене: гранями, ребрами, вершинами. Параметр pScene является указателем на сцену, которая посылает запрос о отображении объекта.
ResetProp(), RemoveArrays() – функции сброса свойств и массивов объекта.
ComplexObject() – подготовка атрибутов для создания составного объекта.
SaveArrays(const char* filename) – отладочная функция сохранения текущих атрибутов объекта в файле.
Базовый объект сцены представлен поверхностью состоящей из треугольных граней (tri-mesh). Объект не хранит свой тип (куб, сфера и т.п.), т.е. работа со сценой не предполагает динамическое изменение структуры объекта, таких как, к примеру, изменение количества меридианов или параллелей как в случае со сферой. Сцена проектируется для отображения большей частью статических объектов: комнат, мебели и т.д.
При запуске функции рисования первым параметром является тип режима отображения объекта, а также, вместо указателя на контекст отображения — указатель на сцену, которая содержит этот контекст.
5.2.3 Описание класса параметрических объектов
class DCLIB2_API dcGFactory
{
public:
dcGFactory();
virtual ~dcGFactory();
// геометрия
void crPlane(dcGObjec
void crRegularPyramid
void crOctahedron(dcG
// цилиндер(разнора
void crRegularCylinde
void crIcosahedron(dc
void crDodecahedron(d
// «helpers»
float Grad2Rad(float grad);
};
Таблица 5.2 – Функции класса параметрических объектов
Имя |
Описание |
crPlane |
Создание плоскости |
crRegularPyramid |
Создание правильной пирамиды |
crOctahedron |
Создание октаэдра |
crRegularCylinde |
Создание цилиндра, призмы, усеченной пирамиды |
crIcosahedron |
Создание икосаэдра |
crDodecahedron |
Создание додекаэдра |
Grad2Rad |
перевод градусов в радианы |
5.2.3.1 Функция создания правильной пирамиды
void dcGFactory::crRe
Таблица 5.3 – Входные параметры
Тип |
Имя |
Описание |
dcGObject |
obj |
указатель на создаваемый объект |
float |
dR |
радиус пирамиды |
float |
dH |
высота пирамиды |
int |
dSeg |
сегментация пирамиды |
5.2.3.2 Функция создания правильной пирамиды
void dcGFactory::crOc
Таблица 5.4 – Входные параметры
Тип |
Имя |
Описание |
dcGObject |
obj |
указатель на создаваемый объект |
float |
dR |
радиус октаэдра |
5.2.3.3 Функции для создания цилиндра, усеченной пирамиды, призма
void dcGFactory::crRe
Для того, чтобы построить цилиндр необходимо задать следующие входные параметры. Радиусы верхнего и нижнего основания равны.
Таблица 5.5 – Входные параметры
Тип |
Имя |
Описание |
dcGObject |
obj |
указатель на создаваемый объект |
int |
dRbot |
радиус верхнего основания цилиндра |
int |
dRtop |
радиус нижнего основания цилиндра |
int |
dH |
высота пирамиды |
float |
fAngle |
угол наклона будет равен 90 градусов |
int |
dSeg |
сегментация цилиндра |
Для того, чтобы построить усеченную пирамиду необходимо задать следующие входные параметры.
Таблица 5.6 – Входные параметры
Тип |
Имя |
Описание |
dcGObject |
obj |
указатель на создаваемый объект |
int |
dRbot |
радиус верхнего основания усеченной пирамиды |
int |
dRtop |
радиус нижнего основания усеченной пирамиды |
int |
dH |
высота пирамиды |
float |
fAngle |
угол наклона равен 90 градусов |
int |
dSeg |
сегментация усеченной пирамиды |
Для того чтобы построить призму необходимо задать следующие входные параметры. Радиусы верхнего и нижнего основания равны
Таблица 5.7 – Входные параметры
Тип |
Имя |
Описание |
dcGObject |
obj |
указатель на создаваемый объект |
int |
dRbot |
радиус верхнего основания призмы |
int |
dRtop |
радиус нижнего основания призмы |
int |
dH |
высота призмы |
float |
fAngle |
угол наклона |
int |
dSeg |
сегментация призмы |
5.2.3.4 Функция создания икосаэдра
void dcGFactory::crIc
Таблица 5.8 – Входные параметры
Тип |
Имя |
Описание |
dcGObject |
obj |
указатель на создаваемый объект |
5.2.4 Описание класса сцены
Для хранения геометрии сцены был создан класс Scene, который содержит все вершины, ребра и грани сцены
class dcGScene
{
public:
dcGScene();
virtual ~dcGScene();
int m_ActiveCamera;
UCHAR m_ucELight; // вектор включенных светильников
CArray<dcGCamera
CArray<dcGObject
CArray<_dcmsLigh
void ParseScript(CStr
void ParseComm(const char* sScript); // выполнить команду
void EnableCamera(int dType=-1);
void EnableLight();
void DrawScene(int dType=0);
void DelObject(dcGObj
protected:
int m_di, m_size;
CString m_sScript;
void CreateObj(int dType);
dcGObject* FindObject(dcGOb
dcGCamera* FindCamera(CStri
_dcmsLight* FindLight(CStrin
}
Таблица 5.9 – Атрибуты класса dcGScene
Тип |
Имя |
Описание |
int |
M_ActiveCamera |
текущая активная камера |
UCHAR |
M_ucELight |
вектор включенных светильников |
dcGCamera* |
M_aCameras |
массив камер сцены |
dcGObjects* |
M_aObjs |
массив объектов сцены |
dcmsLight* |
M_aLight |
массив светильников |
ParseScript(CStr
ParseComm(const char* sScript) – выполнить команду.
EnableCamera(int dType) – включить камеру номер dType.
EnableLight() – включить освещение.
DrawScene(int mode) – отобразить сцену в режиме mode.
DelObject(dcGObj
CreateObject(int dType) – создать объект указанного типа.
FindObject-Camer
Класс dcGScene является фасадным классом, скрывающий от пользователя механизм взаимодействия объектов всей графической библиотеки. Пользователю предлагаются функции обращения к классу с запросом, оформленном на внутреннем языке модуля. Данный класс содержит указатели на все базы данных сцены: объекты, камеры, источники света, текстуры. Через него можно управлять взаимодействием баз данных сцены, получать управление над объектами сцены.
5.3 Описание класса контекста OpenGL
Для более удобной работы с контекстом вывода OpenGL был разработан и частично реализован класс COpenGL
class COpenGL
{
public:
COpenGL();
virtual ~COpenGL();
HGLRC m_hGLContext;
int m_GLPixelIndex;
BOOL StartGL(HDC hDC);
BOOL SetWindowPixelFo
BOOL CreateViewGLCont
void InitViewport(int dStartX,int dStartY,int dDX,int dDY);
// перегрузка функции вида
void ViewMode(GLdoubl
void ViewMode(GLdoubl
GLdouble znear,GLdouble zfar);// gluFrustum
////////////////
}
Таблица 5.9– Атрибуты класса
Тип |
Имя |
Описание |
HGLRC |
m_hGLContex |
дескриптор контекста вывода OpenGL |
int |
m_GLPixelIndex |
Индекс формата представления пикселов. |
COpenGL() – конструктор класса.
~COpenGL() – деструктор класса, очищающий и уничтожающий контекст OpenGL.
StartGL(HDC hDC) – инициализация контекста OpenGL.
SetWIndowPixelFo
CreateViewGLCont
InitViewport(int dStartX,int dStartY,int DX,int DY) – инициализация порта вывода.
ViewMode(…) – установка матриц вида, настройка
5.4 Описание формата графической БД
5.4.1 Внутренний формат графической БД
Внутренним форматом графической БД является информация об объектах, параметры которых задаются и изменяются с клавиатуры.
Параметры объектов:
- для пирамиды задается радиус основания, высота, сегментация;
- для усеченной пирамиды задается радиус нижнего и верхнего основания, высота, сегментация;
- для конуса – радиус основания и высота, сегментация;
- для цилиндра – радиус и высота, сегментация;
- для октаэдра – радиус;
- для додекаэдра – радиус;
5.4.2 Внешний формат графической БД
Для сохранения иерархии объектов сцены во внешний файл и для загрузки сцены используется сериализация. Сериализация – это процесс сохранения текущего состояния объекта на каком-либо устройстве постоянного хранения (в файле или на диске) с возможностью последующего восстановления этого состояния.
6 ТЕСТОВЫЕ ПРИМЕРЫ
, с целью показать правильность отображения призмы, октаедра, икосаэдра, пирамиды с пятиугольным основанием, усеченной пирамиды с пятиугольным основанием, цилиндра.
На данном рисунке отображен икосаэдр в 3Dmax
Приведем пример построения параметрических фигур в 3Dmax и в выполненной курсовой работе
Рисунок 6.1-Икосаэдр в 3Dmax
На данном рисунке отображен икосаэдр нарисованный в данном курсовом проекте.
Рисунок 6.2-Икосаэдр в выполненном курсовом проекте
На данном рисунке отображен цилиндр 3Dmax
Рисунок 6.3-Цилиндр в 3Dmax
На данном рисунке отображен цилиндр нарисованный в данном курсовом проекте.
Рисунок 6.4-Цилиндр в выполненном курсовом проекте
На данном рисунке отображена пирамида с пятиугольным основанием 3Dmax
Рисунок 6.5- пирамида с пятиугольным основанием в 3Dmax
На данном рисунке отображена пирамида с пятиугольным основанием нарисованный в данном курсовом проекте.
Рисунок 6.6- пирамида с пятиугольным основанием в выполненном курсовом проекте
На данном рисунке отображен октаэдр в 3Dmax
Рисунок 6.7- октаэдр в 3Dmax
На данном рисунке отображен октаэдр нарисованный в данном курсовом проекте.
Рисунок 6.8- октаэдр в выполненном курсовом проекте
На данном рисунке отображена призма 3Dmax
Рисунок 6.9- призма в 3Dmax
На данном рисунке отображепризма нарисованный в данном курсовом проекте.
Рисунок 6.10- призма в выполненном курсовом проекте
На данном рисунке отображена усеченная пирамида с пятиугольным основанием 3Dmax
6.11- пирамида с пятиугольным основанием в 3Dmax
На данном рисунке отображен пирамида с пятиугольным основанием нарисованный в данном курсовом проекте.
Рисунок 6.12- пирамида с пятиугольным основанием в выполненном курсовом проекте
ЗАКЛЮЧЕНИЕ
В данном проекте была реализована интерактивная система трехмерного графического моделирования на базе библиотеки OpenGL, позволяющая отображать, параметризироват
Программа обеспечивает решение следующих задач: реализация заданного множества параметризирован
Таким образом, этот проект может быть использован в любом учебном заведении, программное обеспечение которого удовлетворяет требованиям, представленным в техническом задании.
В дальнейшем проект может быть улучшен и обновлен в соответствии с нововведенными требованиями.
ПЕРЕЧЕНЬ ССЫЛОК
1. Роджерс Д., Адамс Дж. Математические основы машинной графики. М.: Машиностроение, 1980 – 234с.
2. Роджерс , Дэвид Ф Алгоритмические основы машинной графики / Пер с англ. С.А.Вичеса М.: Мир, 1989 — 503с.
3. Шикин А.В. Боресков А.В. Компьютерная графика. Динамика, реалистические изображения. – М.: ДИАЛОГ-МИФИ, 1996. – 288с.
4. Аммерал Л. Принципы программирования в машинной графике. М.: «Сол Систем», 1992. – 224с.
5. Аммерал Л. Интерактивная трехмерная машинная графика. М.: «Сол Систем», 1992. – 317с.
6. Пол Айра Объектно-ориенти
7. Курс лекций по предмету «Графическое и геометрическое моделирование».
8. Организация взаимодействия человека с техническими средствами АСУ. В 7 кн. Кн. 4. Отображение информации; Практ. пособие/В.М. Гасов, А.И. Коротаев, С.И. Сенькин; Под ред. В.Н. Четверикова. – М.: Высш. шк., 1990. – 111 с.: ил.
9. Динамика, реалистическое изображения, Препарта Ф., Шеймос М. Вычислительная геометрия: Введение.demo.de
10. Инетернет страницы http://arcana.co
ПРИЛОЖЕНИЕ А
Техническое задание
А.1 Общие сведения
Полное наименование курсового проекта (КП) — «Разработка и реализация с помощью библиотеки OpenGL системы трехмерного графического моделирования. Журнальный столик».
КП проектируется студенткой 3-го курса Донецкого государственного института искусственного интеллекта (ДГИИИ), факультета СКИТ, группы ПО-20а Кочетковой Марией Геннадиевной.
Задание выдано кафедрой ПОИС.
Плановый срок начала работы по созданию подсистемы 28 февраля 2003 года, дата защиты – 5 июня 2003 года.
А.2 Назначение и цели создания проекта
КП предполагается использовать для наглядной демонстрации параметризирован
Цель создания курсового проекта: изучить структуру построения параметризирован
А.3 Характеристика объекта автоматизации
А.3.2 Сведения об условиях эксплуатации КП
Данный программный продукт применим в учебных целях при изучении графического геометрического моделирования. Предназначен для студентов, слушающих курс лекций: «ГГМ»
А.4 Требования к проекту
Необходимо реализовать компьютерную систему трехмерного графического моделирования.
А.4.1 Требования к КП в целом
Программа должна обеспечивать решение таких задач:
— реализация заданного множества параметризирован
– призма;
– цилиндр;
– додекаэдр;
– икосаэдр;
– пирамида с пятиугольным основанием;
– усеченная пирамида с пятиугольным основанием.;
– октаэдр;
— реализация сложного объекта – журнальный столик (см. рис. А1);
- разработка структуры объектов;
- движения по заданной траектории заданного набора параметризирован
- реализация типичных операций управления «камерой» при визуализации и элементов управления объектом;
- возможность редактирования и манипулирования объектами в графической БД;
- разработка системы помощи.
- вызов всех функций реализуется в главном меню и продублирован в виде кнопок;
— загрузка и сохранения всех параметров сцены в файл данных;
— корректный выход из программы (без зависаний приложения);
— реализация планировки сцены (визуализация координатных осей);
— реализация заданного расположения и направления камеры;
— выбор типа проецирования;
— изменение размеров сцены;
— реализация всех аффинных преобразований для объекта с возможностью редактирования параметров: перенос, масштабирование, вращение вокруг каждой из осей, сдвиг, отражение вокруг каждой из осей.
А.4.2 Требования к видам обеспечения
А.4.2.1 Требования к программному обеспечению
К программному обеспечению (ПО) предъявляется следующее требование:
— операционная система – Microsoft Windows 95, 98, NT;
— стандартные библиотеки – Visual C++.
А.4.2.3 Требования к техническому обеспечению
- тип компьютера – INTEL 5x 86;
- объем памяти не менее RAM 64Мб;
- монитор типа SVGA, т.к. предполагается использование цветного графического интерфейса и высокого разрешения.
А.4.2.4 Требования к организационному обеспечению
Организационное обеспечение должно включать пояснительную записку со следующими приложениями:
- техническое задание;
— руководство пользователя;
- экранные формы;
- листинги основных блоков программы;
- пример файла графической БД, содержащего основные объекты системы.
А.4.2.5. Требования к математической модели
В данном КП производятся аффинные преобразования в пространстве, для этого используется матрица размерностью 4*4.
В КП простые объекты: октаэдр, додекаэдр, икосаэдр рисуется методом медианы и параллелей.
Закрашивание производится методом Гуро.
Закрашивание производится линиями, так как данный алгоритм получил широкое распространение в компьютерной графике.
А.5 Стадии и этапы разработки ПП
Стадии и этапы разработки ПП представлены в таблице А.5.1.
Таблица А.5.1- Стадии и этапы разработки ПП
№ |
Этапы работы |
Срок выполнения, недели |
---|---|---|
1. |
Постановка задания. Выбор темы курсового проекта. |
1-2 |
2. |
Разработка технического задания |
2-3 |
3. |
Анализ структуры программы и графических геометрических методов. |
3-4 |
4. |
Создания графической и геометрической математической модели. |
5-8 |
5. |
Разработка интерфейса и программирование |
9-10 |
6. |
Отладка программы |
11-12 |
7. |
Написание программной документации и оформления пояснительной записки. |
13-14 |
8. |
Защита КП. |
15-16 |
Приложение Б
РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ
Б.1 Установка программы и комплект поставки ПО
Для установки программы необходимо распаковать ее из архива “3D-mash.sfx.exe
Далее необходимо запустить приложение «3D-mash.exe», после чего появляется главное окно приложения. Работа с ПП осуществляется при помощи мыши и клавиатуры. После запуска исполняемого файла, на экране появляется приложение и отдельная кнопочная панель, внешний вид которого представлен на рисунке В.1.
Б.2 Описание работы программы
После запуска программы 3D-mash.exe появится окно приложения и отдельная кнопочная панель. Окно приложений содержит следующее меню: меню «Файл», меню «Объект», меню «Вид», меню «Сдвиг\Отражение
Меню «Файл» позволяет создать новую сцену, сохранить файл с определенными параметризованны
Меню «Объект» предназначено для выбора и рисования параметрических объектов (призма, цилиндр, октаэдр, додекаэдр, икосаэдр, пирамида, усеченная пирамида). Также при помощи этого меню мы можем выбирать объект, задавать свойства и материалы выбранного объекта, удалять его. Для изменения параметров фигуры необходимо выбрать в этом меню «Свойства», после этого выплывет диалоговое окно для выбранного объекта поменять его параметры (радиус, высоту, количество аппроксимаций и т.д.). Если нужно поменять или выбрать материал объекту требуется выбрать в этом меню «Материалы», при появлении диалогового окна указать желаемый материал.
Меню «Вид» позволяет выбрать желаемый вид объекта: вид слева, сверху, спереди, в перспективе, а также развернуть объект во весь экран и выбирать свойство камеры и света. При выборе в этом меню «Свойства камеры» появляется диалоговое окно, в котором можно указывать параметры камеры (фокус, глаз, направления верха), а также можно изменить цвет фона, удалить или отобразить координатные оси и грани объекта. При выборе в меню «Свет» появляется окно, в котором можно включить и выключить источники света, указать их позицию, направление, угол под которым он будет падать на объект, цвет и интенсивность изменении света.
Меню «Сдвиг\Отражение
О программе и ее использовании можно узнать больше, выбрав меню «Помощь».
Кнопочная панель, представленная на рисунке В2, содержит такие кнопки:
- L-загрузить сохраненныъй файл;
- N-создать новый файл;
- S-сохранить параметры сцены в файл;
- C-отчистить сцену;
- камера — при нажатии выплавает окно со свойствами камеры: основные коэффициент увеличение (разброс точек), смещение по оси Х, смещение по оси У, положение камер(окуляр,фок
- свет — при нажатии появляется окно, в котором можно включить и выключить источники света, выбрать указать их позицию, направление, угол под которым он будет падать на объект, цвет можно указывать от 0 до 1, интенсивность изменении света изменяется от 0 до 128, чем больше экспоненета, тем ярче источник света.
- свойства — после этого выплывет диалоговое окно для выбранного объекта поменять его параметры: радиус, высоту, сегментация, угол наклона. Трансформации Т-это перенос, R- поворот, S- масштабирование. Можно менять прозрачность объекта прозрачность меняяется от 0 до 255, чем выше цифра, тем менее прозрачный объект. Меняется также цвет объекта от о до 255.
- пирамида- при нажатии появится окно, в котором нужно указать название пирамиды, высоту, радиус нижнего основания, сегментацию, точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности;
- усеченная пирамида- при нажатии появится окно, в котором нужно указать название усеченной пирамиды, высоту, радиус нижнего и верхнего основания, сегментацию, точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности;
- призма- при нажатии появится окно, в котором нужно указать название призмы, высоту, радиус нижнего основания, сегментацию, угол наклона точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности;
- цилиндр- при нажатии появится окно, в котором нужно указать название цилиндр, высоту, радиус нижнего основания, сегментацию, точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности.
- октаэдр- при нажатии появится окно, в котором нужно указать название октаэдра, радиус, точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности.
- додекаэдр- при нажатии появится окно, в котором нужно указать название додекаэдра, точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности.
- икосаэдр- при нажатии появится окно, в котором нужно указать название икосаэдра, точку привязки, цвет, при желании провести с объектом аффинные преобразования (перенос, поворот, масштаб), коээфициент прозрачности.
Приложение В
ЭКРАННЫЕ ФОРМЫ
Рисунок В.1- Главное окно приложения с меню и копками
Рисунок В2-окно параметров сцены
Рисунок В.3-Окно параметров камеры
Рисунок В.4-Окно ведения графической БД
Рисунок В.5-Изображение сложного объекта и окно его параметров
Рисунок В.6-Изображени объекта и окно его параметров(прими
Рисунок В.7- Окно параметров источника света
Рисунок В.8-Окно параметров всех аффиных преобразований
Рисунок В.9-Изображение трех ортогональных проекций
Рисунок В.10-Изображение проекции с индивидуальными параметрами по варианту задания
Рисунок В.11-Окно загрузки и сохранение параметров сцены в файл
Рисунок В.12-Окно помощи по системе
ЛИСТИНГ ПРОГРАММЫ
Программирование камеры и света
// dcGScene.cpp: implementation of the dcGScene class.
//
#include «stdafx.h»
//#include «Ogl3.h»
#include «dcGScene.h»
#include «dcGAscImport.h»
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FI
#define new DEBUG_NEW
#endif
dcGScene::dcGSce
{
m_ucELight = 0;
m_ActiveCamera = 0;
}
dcGScene::~dcGSc
{
m_aObjs.RemoveAl
}
void dcGScene::ParseS
{
if (vstr.Left(4).Co
{
FILE *inFile;
char buf[512];
if (inFile = fopen(vstr,»rt»)
{
ZeroMemory(buf,5
while(fgets(buf,
{
ParseComm(buf);
ZeroMemory(buf,5
}
fclose(inFile);
}
}
}
void dcGScene::ParseC
{
CString vstr;
m_sScript.Format
m_di = 0;
m_size = m_sScript.GetLen
vstr = getWord();
////////////////
// объекты
if (vstr.CompareNoC
{ CommCreate(); goto skip_level; }
if (vstr.CompareNoC
{ CommTrans(); goto skip_level; }
if (vstr.CompareNoC
{ CommMaterial(); goto skip_level; }
if (vstr.CompareNoC
{ CommTexture(); goto skip_level;}
if (vstr.CompareNoC
{ CommSetTexture()
if (vstr.CompareNoC
{ CommOffset(); goto skip_level; }
if (vstr.CompareNoC
{ CommEnable(); goto skip_level; }
if (vstr.CompareNoC
{ CommSetColor(); goto skip_level; }
if (vstr.CompareNoC
{ CommSetPivot(); goto skip_level; }
if (vstr.CompareNoC
{ CommLink(); goto skip_level; }
if (vstr.CompareNoC
{ CommShow(); goto skip_level; }
if (vstr.CompareNoC
{ CommSetShow(); goto skip_level; }
#ifdef DCGOBJ_FLIP_AND_
if (vstr.CompareNoC
{ CommFlipShift(); goto skip_level; }
#endif
////////////////
// камеры
if (vstr.CompareNoC
{ CommCamera(); goto skip_level; }
if (vstr.CompareNoC
{ CommCameraPos(); goto skip_level; }
if (vstr.CompareNoC
{ CommCameraActive
////////////////
// светильики
if (vstr.CompareNoC
{ CommLight(); goto skip_level; }
if (vstr.CompareNoC
{ CommLightPos(); goto skip_level; }
if (vstr.CompareNoC
{ CommLightCol(); goto skip_level; }
if (vstr.CompareNoC
{ CommLightEnable(
////////////////
if (vstr.CompareNoC
{ CommLoad(); goto skip_level; }
if (vstr.CompareNoC
{ CommImportAsc(); goto skip_level; }
if (vstr.CompareNoC
{ CommRemoveAll(); goto skip_level; }
if (vstr.CompareNoC
{ CommRemoveObject
if (vstr.CompareNoC
{ CommRenameObject
skip_level:
; // skipped
}
void dcGScene::CommCr
{
CString vstr;
vstr = getWord();
if (vstr.CompareNoC
{
CreateObj(1); // Plane Seg:1(default)
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(2); // Box Side:1 1 1(default)
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(3); // Regular Pyramid
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(4); // Octahedron
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(5); // prism
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(6); // cylinder
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(7); // trunc_pyramid
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(8); // icosahedron
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(9); // dodecahedron
goto skip_level;
}
if (vstr.CompareNoC
{
CreateObj(10); // hemisphere
goto skip_level;
}
skip_level:
; // skipped
}
void dcGScene::CommTr
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// Scale
vstr = getWord();
if (vstr[0]!=’s’ && vstr[0]!=’S’) goto trans_label;
pObject->sx = (GLfloat)atof(vs
vstr = getWord(); pObject->sy = (GLfloat)atof(vs
vstr = getWord(); pObject->sz = (GLfloat)atof(vs
// Trans
if (m_di>=m_size) goto skip_label;
vstr = getWord();
trans_label:
if (vstr[0]!=’t’ && vstr[0]!=’T’) goto rotate_label;
pObject->dx = (GLfloat)atof(vs
vstr = getWord(); pObject->dy = (GLfloat)atof(vs
vstr = getWord(); pObject->dz = (GLfloat)atof(vs
// Rot’ate
if (m_di>=m_size) goto skip_label;
vstr = getWord();
rotate_label:
pObject->rx = (GLfloat)atof(vs
vstr = getWord(); pObject->ry = (GLfloat)atof(vs
vstr = getWord(); pObject->rz = (GLfloat)atof(vs
skip_label:
;
}
#ifdef DCGOBJ_FLIP_AND_
void dcGScene::CommFl
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// Shift
vstr = getWord();
if (vstr[0]!=’s’ && vstr[0]!=’S’) goto flip_label;
pObject->m_fShif
vstr = getWord(); pObject->m_fShif
vstr = getWord(); pObject->m_fShif
// Flip
if (m_di>=m_size) goto skip_label;
vstr = getWord();
flip_label:
pObject->m_bFlip
vstr = getWord(); pObject->m_bFlip
vstr = getWord(); pObject->m_bFlip
skip_label:
;
}
#endif
void dcGScene::CommOf
{
CString vstr;
vstr = getText();
dcGObject *pObject;
GLfloat vpar[3];
pObject = FindObject(0,vst
// Scale
vstr = getWord();
if (vstr[0]!=’s’ && vstr[0]!=’S’) goto trans_label;
vpar[0] = (GLfloat)atof(vs
vstr = getWord();vpar[1
vstr = getWord();vpar[2
ApplyChanges(pOb
// Trans
if (m_di>=m_size) goto skip_label;
vstr = getWord();
trans_label:
if (vstr[0]!=’t’ && vstr[0]!=’T’) goto rotate_label;
vpar[0] = (GLfloat)atof(vs
vstr = getWord();vpar[1
vstr = getWord();vpar[2
ApplyChanges(pOb
//pObject->dx += vpar[0];
//vstr = getWord(); pObject->dy += vpar[1];
//vstr = getWord(); pObject->dz += vpar[2];
// Rot’ate
if (m_di>=m_size) goto skip_label;
vstr = getWord();
rotate_label:
vpar[0] = (GLfloat)atof(vs
vstr = getWord();vpar[1
vstr = getWord();vpar[2
ApplyChanges(pOb
skip_label:
;
}
void dcGScene::CommMa
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// Ambient
if (m_di>=m_size) goto skip_label;
vstr = getWord();
if (vstr[0]!=’a’ && vstr[0]!=’A’) goto diffuse_label;
pObject->ambient
vstr = getWord(); pObject->ambient
vstr = getWord(); pObject->ambient
pObject->ambient
// Diffuse
if (m_di>=m_size) goto skip_label;
vstr = getWord();
diffuse_label:
if (vstr[0]!=’d’ && vstr[0]!=’D’) goto specular_label;
pObject->diffuse
vstr = getWord(); pObject->diffuse
vstr = getWord(); pObject->diffuse
pObject->diffuse
// Specular
if (m_di>=m_size) goto skip_label;
vstr = getWord();
specular_label:
if (vstr[1]!=’p’ && vstr[1]!=’P’) goto shininess_label;
pObject->specula
vstr = getWord(); pObject->specula
vstr = getWord(); pObject->specula
pObject->specula
// Shininess
if (m_di>=m_size) goto skip_label;
vstr = getWord();
shininess_label:
pObject->shinine
skip_label:
;
}
void dcGScene::CommEn
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// hasMaterial
vstr = getWord();
pObject->hasMate
vstr = getWord();
pObject->hasText
}
void dcGScene::CommSh
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// show:
vstr = getWord();
pObject->IsVis = atoi(vstr.Mid(5)
}
void dcGScene::CommSe
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// show:
vstr = getWord();
pObject->m_ucMod
ApplyChanges(pOb
}
void dcGScene::CommSe
{
CString vstr;
int dOff = 0;
dcGObject *pObject;
vstr = getText();
pObject = FindObject(0,vst
vstr = getWord();
// Pivot Pos
if (m_di>=m_size) goto skip_label;
if (vstr[0]!=’p’ && vstr[0]!=’P’) goto skip_label;
pObject->px = (GLfloat)atof(vs
vstr = getWord();
pObject->py = (GLfloat)atof(vs
vstr = getWord();
pObject->pz = (GLfloat)atof(vs
skip_label:
;
}
void dcGScene::CommSe
{
CString vstr;
int dOff = 0;
dcGObject *pObject;
vstr = getText();
pObject = FindObject(0,vst
vstr = getWord();
// Pivot Pos
if (m_di>=m_size) goto skip_label;
if (vstr[0]!=’c’ && vstr[0]!=’C’) goto skip_label;
pObject->color[0
vstr = getWord();
pObject->color[1
vstr = getWord();
pObject->color[2
vstr = getWord();
pObject->color[3
skip_label:
;
}
////////////////
void dcGScene::CommCa
{
CString vstr;
int dLast;
dLast = m_aCameras.GetSi
m_aCameras.SetSi
vstr = getText();
m_aCameras[dLast
vstr = getWord();
if (vstr.CompareNoC
{
m_aCameras[dLast
m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
}
if (vstr.CompareNoC
{ // Perspective
m_aCameras[dLast
m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
vstr = getWord(); m_aCameras[dLast
}
skip_level:
; // skipped
}
void dcGScene::CommCa
{
CString vstr;
int dOff = 0;
vstr = getText();
dcGCamera *pObject;
pObject = FindCamera(vstr)
vstr = getWord();
if (vstr.CompareNoC
{
dOff = 1;
vstr = getWord();
}
// Trans
if (m_di>=m_size) goto skip_label;
if (vstr[0]!=’t’ && vstr[0]!=’T’) goto rotate_label;
pObject->trans[0
vstr = getWord();
pObject->trans[1
vstr = getWord();
pObject->trans[2
// Rot’ate
if (m_di>=m_size) goto skip_label;
vstr = getWord();
rotate_label:
pObject->rot[0] = pObject->rot[0]*
vstr = getWord();
pObject->rot[1] = pObject->rot[1]*
vstr = getWord();
pObject->rot[2] = pObject->rot[2]*
skip_label:
;
}
void dcGScene::CommCa
{
CString vstr;
int vi, vs;
BOOL bFind=FALSE;
vstr = getText();
vs = m_aCameras.GetSi
vi = 0;
while(vi<vs && !bFind)
if (m_aCameras[vi].
else vi++;
if (bFind)
m_ActiveCamera = vi;
else
m_ActiveCamera = 0;
}
void dcGScene::CommLi
{
CString vstr;
int dLast;
vstr = getText();
_dcmsLight *pObject = 0;
pObject = FindLight(vstr);
if (pObject) return;
dLast = m_aLight.GetSize
m_aLight.SetSize
//vstr = getText();
m_aLight[dLast].
// Exp
vstr = getWord();
m_aLight[dLast].
// cutoff
vstr = getWord();
m_aLight[dLast].
m_aLight[dLast].
skip_label:
;
}
void dcGScene::CommLi
{
CString vstr;
int dOff = 0;
vstr = getText();
_dcmsLight *pObject;
pObject = FindLight(vstr);
vstr = getWord();
if (vstr.CompareNoC
{
dOff = 1;
vstr = getWord();
}
// Pos
if (m_di>=m_size) goto skip_label;
if (vstr[0]!=’p’ && vstr[0]!=’P’) goto dir_label;
pObject->pos[0] = pObject->pos[0]*
vstr = getWord();
pObject->pos[1] = pObject->pos[1]*
vstr = getWord();
pObject->pos[2] = pObject->pos[2]*
pObject->pos[3] = 1.0;
// Direction
if (m_di>=m_size) goto skip_label;
vstr = getWord();
dir_label:
pObject->dir[0] = pObject->dir[0]*
vstr = getWord();
pObject->dir[1] = pObject->dir[1]*
vstr = getWord();
pObject->dir[2] = pObject->dir[2]*
pObject->dir[3] = 1.0;
skip_label:
;
}
void dcGScene::CommLi
{
CString vstr;
int dOff = 0;
vstr = getText();
_dcmsLight *pObject;
pObject = FindLight(vstr);
vstr = getWord();
// Diffuse
if (m_di>=m_size) goto skip_label;
if (vstr[0]!=’c’ && vstr[0]!=’C’) goto skip_label;
pObject->color[0
vstr = getWord(); pObject->color[1
vstr = getWord(); pObject->color[2
pObject->color[3
skip_label:
;
}
void dcGScene::CommLi
{
CString vstr;
int dOff = 0;
vstr = getText();
_dcmsLight *pObject;
pObject = FindLight(vstr);
vstr = getWord();
// Vector
vstr = vstr.Mid(7);
m_ucELight = 0;
for(int vi=0;vi<8;vi++)
if (vstr[vi]==’1′) m_ucELight |= (1<<vi);
//vstr.Empty();
//vstr.Format(«%
//MessageBox(0,v
skip_label:
;
}
////////////////
// Иное
void dcGScene::CommLo
{
CString vstr;
// hasMaterial
vstr = getText();
ParseScript(vstr
}
void dcGScene::CommSe
{
CString vstr;
int vi,vs;
char vf = 1;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
// Texture name
vstr = getWord();
if (vstr[0]!=’n’ && vstr[0]!=’N’) goto inv_label;
vstr = getText();
vs = m_aDibs.GetSize(
vi = 0;
while(vi<vs && vf)
{
if (vstr.CompareNoC
else vi++;
}
if (vf==0)
{
CSize cs;
pObject->dTexInd
cs = m_aDibs[vi].cDib
pObject->dTexX = cs.cx;
pObject->dTexY = cs.cy;
}
if (m_di>=(m_size-1
vstr = getWord();
inv_label:
if (vstr[0]!=’i’ && vstr[0]!=’I’) goto skip_label;
pObject->dTexInv
/*
// Rot’ate
if (m_di>=m_size) goto skip_label;
vstr = getWord();
rotate_label:
pObject->rx = (GLfloat)atof(vs
vstr = getWord(); pObject->ry = (GLfloat)atof(vs
vstr = getWord(); pObject->rz = (GLfloat)atof(vs
*/
skip_label:
;
}
void dcGScene::CommTe
{
CString vstr1,vstr2;
int dLast;
// Load
vstr1 = getText(); // path+filename
vstr2 = getText(); // texture name
LoadTexture(vstr
}
void dcGScene::CommLi
{
CString vstr;
CString tst;
int dLast;
dcGObject *pObject1;
dcGObject *pObject2;
BOOL has3=FALSE;
vstr = getText();
pObject1 = FindObject(0,vst
vstr = getText();
pObject2 = FindObject(0,vst
if (m_di>=(m_size-1
vstr = getText();
has3 = TRUE;
skip_label:
dLast = pObject1->m_aObj
if (/*dLast==0 ||*/ has3)
{
dcGObject tmpObj;
tmpObj = *pObject1;
pObject1->m_aObj
pObject1->m_aObj
pObject1->m_aObj
pObject1->Comple
pObject1->m_sObj
pObject2->m_sObj
tmpObj.RemoveArr
}
else
{
pObject1->m_aObj
pObject1->m_aObj
pObject2->m_sObj
}
CString delstr = pObject2->m_sObj
DelObject(0,dels
}
void dcGScene::CommIm
{
CString vstr;
dcGAscImport cAsc;
vstr = getText();
cAsc.ImportASC(v
}
void dcGScene::CommRe
{
m_aDibs.RemoveAl
m_aCameras.Remov
//m_aLight.Remov
m_aObjs.RemoveAl
m_aObjs.FreeExtr
//m_ActiveCamera = 0;
m_ucELight = 0;
}
void dcGScene::CommRe
{
CString vstr;
vstr = getText();
DelObject(0,vstr
}
void dcGScene::CommRe
{
CString vstr;
vstr = getText();
dcGObject *pObject;
pObject = FindObject(0,vst
vstr = getText();
pObject->m_sObjN
pObject->m_sObjN
}
////////////////
////////////////
////////////////
void dcGScene::Create
{
dcGFactory dcgFact;
int dPar[6];
float fPar[6];
int dLast;
CString vstr,tstr;
m_aObjs.SetSize(
//m_aObjs.FreeEx
dLast = m_aObjs.GetSize(
// Name
vstr = getText();
//m_aObjs[dLast]
//ZeroMemory(m_a
m_aObjs[dLast].m
m_aObjs[dLast].m
m_aObjs[dLast].m
// Geometry
switch(dType)
{
case 1: // create plane
vstr = getWord();
dPar[0] = atoi(vstr.Mid(4)
dcgFact.crPlane(
//m_aObjs[dLast]
break;
case 2: // create Box
vstr = getWord();
dPar[0] = atoi(vstr.Mid(5)
vstr = getWord();dPar[1
vstr = getWord();dPar[2
dcgFact.crBox(m_
//m_aObjs[dLast]
break;
case 3: // create Regular Pyramid
vstr = getWord();
fPar[0] = atof(vstr.Mid(7)
vstr = getWord();fPar[1
vstr = getWord();dPar[0
dcgFact.crRegula
//m_aObjs[dLast]
break;
case 4: // create Octahedron
vstr = getWord();
fPar[0] = atof(vstr.Mid(7)
dcgFact.crOctahe
//m_aObjs[dLast]
break;
case 5: // create Prism
// worked
vstr = getWord();
dPar[0] = atoi(vstr.Mid(7)
vstr = getWord();dPar[1
vstr = getWord();fPar[0
m_aObjs[dLast].m
vstr = getWord();dPar[2
dcgFact.crRegula
//m_aObjs[dLast]
break;
case 6: // create Cylinder
vstr = getWord();
dPar[1] = atoi(vstr.Mid(7)
vstr = getWord();dPar[2
vstr = getWord();dPar[0
dcgFact.crRegula
//m_aObjs[dLast]
break;
case 7: // create Truncated Pyramid
vstr = getWord();
dPar[1] = atoi(vstr.Mid(7)
vstr = getWord();dPar[2
vstr = getWord();dPar[3
vstr = getWord();dPar[0
dcgFact.crRegula
//m_aObjs[dLast]
break;
case 8: // create Icosahedron
dcgFact.crIcosah
//m_aObjs[dLast]
break;
case 9: // create Dodecahedron
dcgFact.crDodeca
//m_aObjs[dLast]
break;
case 10: // create Hemishpere
vstr = getWord();
fPar[0] = atof(vstr.Mid(7)
vstr = getWord();dPar[0
vstr = getWord();dPar[1
dcgFact.crHemisp
//m_aObjs[dLast]
break;
}
// Color
vstr = getWord();
m_aObjs[dLast].c
vstr = getWord(); m_aObjs[dLast].c
vstr = getWord(); m_aObjs[dLast].c
vstr = getWord(); m_aObjs[dLast].c
// Pivot
vstr = getWord();
m_aObjs[dLast].p
vstr = getWord(); m_aObjs[dLast].p
vstr = getWord(); m_aObjs[dLast].p
// Texture Map
vstr = getWord();
vstr = getText();
if (vstr.CompareNoC
{
if (vstr.CompareNoC
{
switch(dType)
{
case 1: // create plane TexMap
dcgFact.crPlaneT
//m_aObjs[dLast]
break;
case 2: // create box TexMap
dcgFact.crBoxTex
//m_aObjs[dLast]
break;
case 7: // create Truncated Pyramid
dcgFact.crRegula
//m_aObjs[dLast]
break;
case 10: // create Hemishpere
dcgFact.crHemisp
//m_aObjs[dLast]
break;
}
}
}
m_aObjs[dLast].h
}
////////////////
// вывод сцены в контекст
void dcGScene::DrawSc
{
int vs,vi;
vs = m_aObjs.GetSize(
if (vs==0) return;
for(vi=0;vi<vs;v
{
glMatrixMode(GL_
glLoadIdentity()
m_aObjs[vi].Draw
}
}
void dcGScene::Enable
{
if (m_aCameras.GetS
if (dType<0)
m_aCameras[m_Act
else
if (dType<m_aCamera
m_aCameras[dType
}
void dcGScene::Camera
{
if (dType<0)
m_aCameras[m_Act
else
if (dType<m_aCamera
m_aCameras[dType
}
void dcGScene::Enable
{
int vi,vs;
GLfloat amb[4] = {0.0,0.0,0.0,1.0
GLfloat diff[4] = {1.0,1.0,1.0,1.0
GLfloat spec[4] = {1.0,1.0,1.0,1.0
vs = m_aLight.GetSize
if (vs==0) return;
for(vi=0;vi<vs;v
{
glLightfv(GL_LIG
glLightfv(GL_LIG
glLightfv(GL_LIG
glLightfv(GL_LIG
glLightfv(GL_LIG
//glLightf(GL_LI
glLighti(GL_LIGH
glLightf(GL_LIGH
}
CString vstr;
CFile cf;
//cf.Open(«dll.d
for(vi=0;vi<vs;v
{
vstr.Empty();
if( (m_ucELight&(1<<
glEnable(GL_LIGH
else
glDisable(GL_LIG
char buf[64];
ZeroMemory(buf,6
vstr.Format(» %d/%d(~%s~)»,vi,
strcpy(buf,vstr)
//cf.Write(&buf,
ZeroMemory(buf,6
vstr.Format(» %d:pos(%f;%f;%f)
strcpy(buf,vstr)
//cf.Write(&buf,
ZeroMemory(buf,6
vstr.Format(» %d:dir(%f;%f;%f)
strcpy(buf,vstr)
//cf.Write(&buf,
ZeroMemory(buf,6
vstr.Format(» %d:e_c(%f;%f)»,v
strcpy(buf,vstr)
//cf.Write(&buf,
//MessageBox(0,v
}
}
// найти объект по имени
dcGObject* dcGScene::FindOb
{
int vf, vi, vs;
BOOL bFind = 0;
CString vstr;
vf = sSearchObj.Find(
if (vf!=-1)
{
vstr = sSearchObj.Left(
if (Leaf==0)
vs = m_aObjs.GetSize(
else
vs = Leaf->m_aObjects
vi = 0;
while(vi<vs && bFind==0)
{
if (Leaf==0)
{
if (vstr.CompareNoC
bFind=1;
}
else
{
if (vstr.CompareNoC
bFind=1;
}
if (bFind==0) vi++;
}
if (bFind==0) return 0;
else
{
if (Leaf==0)
return FindObject(&m_aO
else
return FindObject(&(Lea
}
}
else
{
if (Leaf==0)
vs = m_aObjs.GetSize(
else
vs = Leaf->m_aObjects
vi = 0;
while(vi<vs && bFind==0)
{
if (Leaf==0)
{
if (sSearchObj.Comp
bFind=1;
}
else
{
if (sSearchObj.Comp
bFind=1;
}
if (bFind==0) vi++;
}
if (bFind==0) return 0;
else
{
if (Leaf==0)
return &m_aObjs[vi];
else
return &(Leaf->m_aObjec
}
}
}
// поиск камеры по имени
dcGCamera* dcGScene::FindCa
{
int vi,vs;
BOOL bFind = FALSE;
vs = m_aCameras.GetSi
vi = 0;
while(vi<vs && !bFind)
if (m_aCameras[vi].
else vi++;
if (bFind)
return &m_aCameras[vi];
else return 0;
}
// поиск камеры по имени
_dcmsLight* dcGScene::FindLi
{
int vi,vs;
BOOL bFind = FALSE;
vs = m_aLight.GetSize
vi = 0;
while(vi<vs && !bFind)
if (m_aLight[vi].na
else vi++;
if (bFind)
return &m_aLight[vi];
else return 0;
}
// удаление объекта
void dcGScene::DelObj
{
int vf, vi, vs;
BOOL bFind = 0;
CString vstr;
//CString ttt;
//ttt.Format(«%s
vf = sSearchObj.Find(
if (vf!=-1)
{
vstr = sSearchObj.Left(
if (Leaf==0)
vs = m_aObjs.GetSize(
else
vs = Leaf->m_aObjects
vi = 0;
while(vi<vs && bFind==0)
{
if (Leaf==0)
{
if (sSearchObj.Comp
bFind=1;
}
else
{
if (sSearchObj.Comp
bFind=1;
}
if (bFind==0) vi++;
}
if (bFind!=0)
{
if (Leaf==0)
DelObject(&m_aOb
else
DelObject(&(Leaf
}
}
else
{
if (Leaf==0)
vs = m_aObjs.GetSize(
else
vs = Leaf->m_aObjects
vi = 0;
while(vi<vs && bFind==0)
{
if (Leaf==0)
{
if (sSearchObj.Comp
bFind=1;
}
else
{
if (sSearchObj.Comp
bFind=1;
}
if (bFind==0) vi++;
}
if (bFind!=0)
{
if (Leaf==0)
{
m_aObjs[vi].Remo
m_aObjs.RemoveAt
m_aObjs.FreeExtr
//return &m_aObjs[vi];
}
else
{
Leaf->m_aObjects
Leaf->m_aObjects
Leaf->m_aObjects
//return &(Leaf->m_aObjec
}
}
}
}
// вернуть указатель на объект по индексу
dcGObject* dcGScene::GetObj
{
if (dIndex>=0 && dIndex<m_aObjs.G
return &(m_aObjs[dIndex
}
void dcGScene::GetObj
{
if (dIndex>=0 && dIndex<m_aObjs.G
pObj = m_aObjs[dIndex];
}
// применение изменений ко всей группе
void dcGScene::ApplyC
{
int vi,vs;
vs = dst->m_aObjects.
switch(sType)
{
case ‘r’:
dst->rx +=p1;dst->ry +=p2;dst->rz +=p3;
if (dst->rx>360.0) dst->rx -= 360.0;
if (dst->ry>360.0) dst->ry -= 360.0;
if (dst->rz>360.0) dst->rz -= 360.0;
if (dst->rx<-360.0) dst->rx += 360.0;
if (dst->ry<-360.0) dst->ry += 360.0;
if (dst->rz<-360.0) dst->rz += 360.0;
break;
case ‘s’:
dst->sx +=p1;dst->sy +=p2;dst->sz +=p3;
break;
case ‘t’:
dst->dx +=p1;dst->dy +=p2;dst->dz +=p3;
break;
}
//for(vi=0;vi<vs
// ApplyChanges(&ds
}
void dcGScene::ApplyC
{
int vi,vs;
vs = dst->m_aObjects.
dst->m_ucMode = Mode;
for(vi=0;vi<vs;v
ApplyChanges(&ds
}
else
{
CFile inFile;
int dLast;
dLast = m_aDibs.GetSize(
m_aDibs.SetSize(
if (inFile.Open(vst
{
if (!m_aDibs[dLast]
MessageBox(0,vst
m_aDibs[dLast].n
m_aDibs[dLast].f
}
else
{
MessageBox(0,vst
}
}
}
// взять слово из скрипта
CString dcGScene::getWor
{
CString vres;
char vch;
vch = m_sScript[m_di];
while(m_di<m_siz
{
vres += m_sScript[m_di];
m_di++;
if (m_di!=m_size) vch = m_sScript[m_di];
}
if (vch==13) {m_di++;m_di++;} // перевод каретки
if (m_di<m_size)
while(m_sScript[
return vres;
}
// взять предложение из скрипта
CString dcGScene::getTex
{
CString vres;
char vch;
vch = m_sScript[m_di];
if (vch==’~’)
{
m_di++;
if (m_di!=m_size) vch = m_sScript[m_di];
while(m_di<m_siz
{
vres += m_sScript[m_di];
m_di++;
if (m_di!=m_size) vch = m_sScript[m_di];
}
}
m_di++;
//if (vch==13) {m_di++;m_di++;} // перевод каретки
if (m_di<m_size)
while(m_sScript[
return vres;
}
Прогарммирование объектов
// dcGFactory.cpp: implementation of the dcGFactory class.
//
////////////////
#include «stdafx.h»
#include «dcGFactory.h»
#include «math.h»
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FI
#define new DEBUG_NEW
#endif
#define myPI 3.14159265358979
////////////////
// Construction/Des
////////////////
dcGFactory::dcGF
{
}
dcGFactory::~dcG
{
}
float dcGFactory::Grad
{
return (myPI*grad)/180.
}
void dcGFactory::crPl
{
int vi,vj, i;
GLfloat x,y,dx,dy;
obj.m_prop[0] = (dSeg+1)*(dSeg+1
obj.m_prop[1] = dSeg*dSeg*2;
obj.vertex = new GLfloat[obj.m_pr
obj.faces = new GLint[obj.m_prop
dx = dy = 1.0f / ((GLfloat)dSeg);
i = 0; y=0.0f;
for(vj=0;vj<=dSe
{
x = 0.0f;
for(vi=0;vi<=dSe
{
obj.vertex[i*3 ] = x;
obj.vertex[i*3+1
obj.vertex[i*3+2
x+=dx;
i++;
}
y+=dy;
}
i=0;
for(vj=0;vj<dSeg
{
for (vi=0+vj*(dSeg+1
{
obj.faces[i*3 ] = vi;
obj.faces[i*3+1] = vi+1;
obj.faces[i*3+2] = vi+dSeg+1;
//obj.faces[i*3 ] = vi;
//obj.faces[i*3+
//obj.faces[i*3+
i++;
obj.faces[i*3 ] = vi+1;
obj.faces[i*3+1] = vi+dSeg+2;
obj.faces[i*3+2] = vi+dSeg+1;
//obj.faces[i*3 ] = vi+1;
//obj.faces[i*3+
//obj.faces[i*3+
i++;
}
}
//CString vstr;
//vstr.Format(«%
//MessageBox(0,v
}
void dcGFactory::crBo
{
int i;
obj.m_prop[0] = 8;
obj.m_prop[1] = 12;
obj.vertex = new GLfloat[obj.m_pr
obj.faces = new GLint[obj.m_prop
for(i=0;i<2;i++)
{
obj.vertex[0 + 12*i] = 0 ;
obj.vertex[1 + 12*i] = 0 ;
obj.vertex[2 + 12*i] = dZ*i;
obj.vertex[3 + 12*i] = 0 ;
obj.vertex[4 + 12*i] = dY;
obj.vertex[5 + 12*i] = dZ*i;
obj.vertex[6 + 12*i] = dX;
obj.vertex[7 + 12*i] = dY;
obj.vertex[8 + 12*i] = dZ*i;
obj.vertex[9 + 12*i] = dX;
obj.vertex[10 + 12*i] = 0;
obj.vertex[11 + 12*i] = dZ*i;
}
i=0;
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=4;o
obj.faces[i]=4;o
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=3;o
obj.faces[i]=3;o
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=2;o
obj.faces[i]=2;o
}
void dcGFactory::crRe
{
int i;
float vfAngleIter;
if (dSeg<3) dSeg = 3;
obj.m_prop[0] = dSeg+2;
obj.m_prop[1] = 2*dSeg;
obj.vertex = new GLfloat[obj.m_pr
obj.faces = new GLint[obj.m_prop
obj.vertex[0] = 0 ;obj.vertex[1] = 0 ;obj.vertex[2] = dH; // Apex
obj.vertex[(dSeg
obj.vertex[(dSeg
vfAngleIter = Grad2Rad(360.0/(
for(i=1;i<=dSeg;
{
obj.vertex[i*3] = cos(vfAngleIter*
obj.vertex[i*3+1
obj.vertex[i*3+2
}
// side
for(i=0;i<dSeg-1
{
obj.faces[i*3 ] = 0; // apex
obj.faces[i*3+1] = i+1;
obj.faces[i*3+2] = i+2;
}
// conection side
obj.faces[i*3]=0
// bottom faces
for(;i<(2*dSeg)-
{
obj.faces[i*3 ] = (dSeg+1); // apex
obj.faces[i*3+1] = i-dSeg+2;
obj.faces[i*3+2] = i-dSeg+1;
}
// conection side
obj.faces[i*3 ] = (dSeg+1);
obj.faces[i*3+1] = 1;
obj.faces[i*3+2] = dSeg;//i-dSeg+1;
}
void dcGFactory::crOc
{
int i;
obj.m_prop[0] = 6;
obj.m_prop[1] = 8;
obj.vertex = new GLfloat[obj.m_pr
obj.faces = new GLint[obj.m_prop
i = 0;
obj.vertex[i] = 0 ;obj.vertex[i+1] = 0 ;obj.vertex[i+2] = dR; i+=3;
obj.vertex[i] = 0 ;obj.vertex[i+1] = dR ;obj.vertex[i+2] = 0 ; i+=3;
obj.vertex[i] = dR ;obj.vertex[i+1] = 0 ;obj.vertex[i+2] = 0 ; i+=3;
obj.vertex[i] = 0 ;obj.vertex[i+1] = -dR;obj.vertex[i
obj.vertex[i] = -dR;obj.vertex[i
obj.vertex[i] = 0 ;obj.vertex[i+1] = 0 ;obj.vertex[i+2] = -dR;
i=0;
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=5;o
obj.faces[i]=5;o
obj.faces[i]=5;o
obj.faces[i]=5;o
}
void dcGFactory::crRe
//void dcGFactory::crRe
{
int i,j;
float vfAngleIter, vfNaklonAngle;
float fCos_dH;
CString vstr;
//MessageBox(0,»
if (dSeg<3) dSeg = 3;
obj.m_prop[0] = dSeg*2+2;
//obj.m_prop[1] = /*top+bottom*/ + /*side*/;
obj.m_prop[1] = dSeg*2 + dSeg*2;
obj.vertex = new GLfloat[obj.m_pr
obj.faces = new GLint[obj.m_prop
ZeroMemory(obj.v
vfAngleIter = Grad2Rad(360.0/(
vfNaklonAngle = Grad2Rad(fAngle)
obj.vertex[0] = 0 ; obj.vertex[1] = 0; obj.vertex[2] = 0; // bottom
if ((float)fAngle==
fCos_dH = 0.0;
else
fCos_dH = cos(vfNaklonAngl
obj.vertex[(dSeg
obj.vertex[(dSeg
obj.vertex[(dSeg
//vstr.Format(«f
//MessageBox(0,v
// bottom vertexes
for(i=1;i<=dSeg;
{
obj.vertex[i*3] = cos(vfAngleIter*
obj.vertex[i*3+1
obj.vertex[i*3+2
}
// top vertexes
// mr
i++;
//vstr.Format(«d
//MessageBox(0,v
// —
j = 0;
for(;i<=2*dSeg+1
{
obj.vertex[i*3] = cos(vfAngleIter*
obj.vertex[i*3+1
obj.vertex[i*3+2
j++;
}
//vstr.Format(«d
//MessageBox(0,v
//vstr.Format(«f
//MessageBox(0,v
// Faces
// bottom side
j = 0;
for(i=1;i<dSeg;i
{
obj.faces[j ] = 0; // bottom
obj.faces[j+1] = i+1;
obj.faces[j+2] = i;
j+=3;
}
// conection side
obj.faces[j]=0;o
// top side
for(i=1;i<dSeg;i
{
obj.faces[j] = dSeg+1; // top
obj.faces[j+1] = dSeg+i+1;
obj.faces[j+2] = dSeg+i+2;
j+=3;
}
// conection side
obj.faces[j]=dSe
// sides
for(i=1;i<dSeg;i
{
obj.faces[j] = i;
obj.faces[j+1] = i+1;
obj.faces[j+2] = dSeg+i+1;
j+=3;
}
// conection side
obj.faces[j]=dSe
// second sides
for(i=1;i<dSeg;i
{
obj.faces[j] = dSeg+i+2;
obj.faces[j+1] = dSeg+i+1;
obj.faces[j+2] = i+1;
j+=3;
}
// conection side
obj.faces[j]=dSe
}
void dcGFactory::crIc
{
int i,j;
obj.m_prop[0] = 12;
obj.m_prop[1] = 20;
obj.vertex = new GLfloat[obj.m_pr
obj.faces = new GLint[obj.m_prop
//for(i=0;i<obj.
i = 0;
// top apex
obj.vertex[i] = 0 ;obj.vertex[i+1] = 0 ;obj.vertex[i+2] = (sqrt(5.0)*0.9)/
// center
float vfGradus;
vfGradus = Grad2Rad(72.0);
for(j=0;j<5;j++)
{
obj.vertex[i] = cos(vfGradus*j)*
obj.vertex[i+1] = sin(vfGradus*j)*
obj.vertex[i+2] = 0.5*0.9 ;
i+=3;
}
for(j=0;j<5;j++)
{
obj.vertex[i] = cos(Grad2Rad(36)
obj.vertex[i+1] = sin(Grad2Rad(36)
obj.vertex[i+2] = -0.5*0.9 ;
i+=3;
}
// bottom apex
obj.vertex[i] = 0 ;obj.vertex[i+1] = 0 ;obj.vertex[i+2] = -(sqrt(5.0)*0.9)
i=0;
// top
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=0;o
obj.faces[i]=0;o
// bottom
obj.faces[i]=11;
obj.faces[i]=11;
obj.faces[i]=11;
obj.faces[i]=11;
obj.faces[i]=11;
// side
obj.faces[i]=1;o
obj.faces[i]=2;o
obj.faces[i]=3;o
obj.faces[i]=4;o
obj.faces[i]=5;o
//—
obj.faces[i]=6 ;obj.faces[i+1]=
obj.faces[i]=7 ;obj.faces[i+1]=
obj.faces[i]=8 ;obj.faces[i+1]=
obj.faces[i]=9 ;obj.faces[i+1]=
obj.faces[i]=10;
}
obj.texvert[0 ] = 1.0;obj.texvert[
obj.texvert[2 ] = 1.0;obj.texvert[
obj.texvert[4 ] = 0.0;obj.texvert[
obj.texvert[6 ] = 0.0;obj.texvert[
obj.texvert[8 ] = 1.0;obj.texvert[
obj.texvert[10] = 1.0;obj.texvert[
obj.texvert[12] = 0.0;obj.texvert[
obj.texvert[14] = 0.0;obj.texvert[
obj.m_prop[2] = 1;
}
void dcGFactory::crRe
{
int i,vi,vj;
float fTexXIter;
obj.texvert = new GLfloat[obj.m_pr
fTexXIter = 1.0/(float)dSeg;
obj.texvert[0] = 0.5;
obj.texvert[1] = 0.0; // bottom
obj.texvert[(dSe
obj.texvert[(dSe
i = 2;
for(vi=0;vi<dSeg
{
obj.texvert[i ] = fTexXIter*vi;
obj.texvert[i+1] = 0.0; // bottom
i+=2;
}
i+=2;
for(vi=0;vi<dSeg
{
obj.texvert[i ] = fTexXIter*vi;
obj.texvert[i+1] = 1.0; // top
i+=2;
}
obj.m_prop[2] = 1;
}
void dcGFactory::crHe
{
int i,vi,vj;
float fTexXIter,fTexYI
obj.texvert = new GLfloat[obj.m_pr
fTexXIter = 1.0/(float)dMer;
fTexYIter = 1.0/(float)dPar;
obj.texvert[0 ] = 1.0;obj.texvert[
i = 2;
for(vi=0;vi<(dPa
{
for(vj=0;vj<(dMe
{
obj.texvert[i ] = 1.0-vi*fTexYIter
obj.texvert[i+1] = vj*fTexXIter;
i+=2;
}
}
obj.m_prop[2] = 1;
}
Выполнение класса объекта
// dcGObject.cpp: implementation of the dcGObject class.
//
////////////////
#include «stdafx.h»
//#include «prb2.h»
#include «dcGObject.h»
#include «dcGScene.h»
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FI
#define new DEBUG_NEW
#endif
////////////////
// Construction/Des
////////////////
dcGObject::dcGOb
{
vertex = 0;
faces = 0;
mask = 0;
texvert = 0;
// m_sObjName = 0;
hasTexture = 0;
dTexInvMode = GL_MODULATE;
m_prop[0] = m_prop[1] = m_prop[2] = 0;
#ifdef DCGOBJ_FLIP_AND_
m_bFlip[0] = m_bFlip[1] = m_bFlip[2] = 0;
m_fShift[0] = m_fShift[1] = m_fShift[2] = 0;
#endif
IsVis = TRUE;
ResetProp(3);
}
dcGObject::dcGOb
{
int vi, vs;
src.m_sObjName.E
src.m_sObjName = m_sObjName;
src.m_ucMode = m_ucMode;
src.m_bType = m_bType;
src.m_fFparam1 = m_fFparam1;
src.RemoveArrays
src.m_prop[0] = m_prop[0];src.m_
vs = m_prop[0]*3; src.vertex = new GLfloat[vs];
memcpy(src.verte
// for(vi=0;vi<vs;v
vs = m_prop[1]*3; src.faces = new GLint[vs];
memcpy(src.faces
// for(vi=0;vi<vs;v
//vs = sizeof(mask); src.mask = new GLubyte[vs];
//memcpy(src.mas
//for(vi=0;vi<vs
src.color[0] = color[0];src.col
src.color[3] = color[3];
src.dx = dx;src.dy = dy;src.dz = dz;
src.rx = rx;src.ry = ry;src.rz = rz;
src.sx = sx;src.sy = sy;src.sz = sz;
#ifdef DCGOBJ_FLIP_AND_
memcpy(src.m_fSh
memcpy(src.m_bFl
#endif
src.hasMaterial = hasMaterial;
src.shininess = shininess;
for(vi=0;vi<4;vi
{
src.ambient [vi] = ambient [vi];
src.diffuse [vi] = diffuse [vi];
src.specular[vi] = specular[vi];
}
src.hasTexture = hasTexture;
src.dTexX = dTexX; src.dTexY = dTexY;
if (m_prop[2])
{
vs =m_prop[0]*2; src.texvert = new GLfloat[vs];
memcpy(src.texve
}
//for(vi=0;vi<vs
src.dTexIndex = dTexIndex;
src.dTexInvMode = dTexInvMode;
vs = m_aObjects.GetSi
src.m_aObjects.S
for(vi=0;vi<vs;v
src.m_aObjects[v
}
dcGObject::~dcGO
{
RemoveArrays();
}
////////////////
// Implementation
////////////////
void dcGObject::Compl
{
if (vertex) delete[] vertex;
if (faces) delete[] faces;
if (mask) delete[] mask;
if (texvert) delete[] texvert;
m_prop[0] = m_prop[1] = m_prop[2] = 0;
vertex = 0;
faces = 0;
mask = 0;
texvert = 0;
dx = dy = dz = 0.0;
rx = ry = rz = 0.0;
sx = sy = sz = 1.0;
hasMaterial = 0;
hasTexture = 0;
dTexInvMode = GL_MODULATE;
// if (m_sObjName) delete[] m_sObjName;
}
void dcGObject::Remov
{
if (vertex) delete[] vertex;
if (faces) delete[] faces;
if (mask) delete[] mask;
if (texvert) delete[] texvert;
m_prop[0] = m_prop[1] = m_prop[2] = 0;
m_aObjects.Remov
vertex = 0;
faces = 0;
mask = 0;
texvert = 0;
dx = dy = dz = 0.0;
rx = ry = rz = 0.0;
sx = sy = sz = 1.0;
hasMaterial = 0;
hasTexture = 0;
dTexInvMode = GL_MODULATE;
m_ucMode = DCGOBJ_FACES;
// if (m_sObjName) delete[] m_sObjName;
}
void dcGObject::Reset
{
if ((bMatTrans&0x01
{
px = py = pz = 0;
dx = dy = dz = 0;
rx = ry = rz = 0;
sx = sy = sz = 1.0f;
}
if ((bMatTrans&0x02
{
hasMaterial = FALSE;
shininess = 0;
for(int i=0;i<4;i++)
ambient[i] = diffuse[i] = specular[i] = 0;
}
}
void dcGObject::SetPr
{
m_prop[0] = dVertex;
m_prop[1] = dFaces;
m_prop[2] = dTexVertex;
}
void dcGObject::Draw(
{
int vs, vk;
glMatrixMode(GL_
if (mode<3) glLoadIdentity()
else mode -=3;
glTranslatef( px, py, pz); // begpivotPoint
//glTranslatef( dx, dy, dz);
glTranslatef( dx*((m_bFlip[0])
glRotatef( rx, 1.0f, 0.0f, 0.0f);
glRotatef( ry, 0.0f, 1.0f, 0.0f);
glRotatef( rz, 0.0f, 0.0f, 1.0f);
glTranslatef(-px
glScalef(sx,sy,s
#ifdef DCGOBJ_FLIP_AND_
GLfloat vm[16];
ZeroMemory(vm,si
vm[0] = (m_bFlip[0])?-1:
//vm[0] = 1;
vm[1] = m_fShift[1];
vm[2] = m_fShift[2];
vm[4] = m_fShift[0];
vm[5] = (m_bFlip[1])?-1:
//vm[5] = 1;
vm[6] = m_fShift[2];
vm[8] = m_fShift[0];
vm[9] = m_fShift[1];
vm[10] = (m_bFlip[2])?-1:
vm[15] = 1;
glMultMatrixf(vm
#endif
vs = m_aObjects.GetSi
for(vk=0;vk<vs;v
{
glPushMatrix();
//m_aObjects[vk]
m_aObjects[vk].D
glPopMatrix();
}
//SaveArrays(«ob
dcGScene* pScn1;
if (pScene!=0)
{
pScn1 = (dcGScene*) pScene;
}
// хёыш юс·хъЄ ёюёЄртэющ Єю фры№°х шфЄш эх шьххЄ ёьvёыр
if (vs!=0) goto stop_draw_obj;
// шэрўх — юс·хъЄ эх ёюёЄртэющ
if (hasMaterial==0)
{
glColor4ub(color
glEnable(GL_COLO
}
else
{
glDisable(GL_COL
glMaterialfv(GL_
glMaterialfv(GL_
glMaterialfv(GL_
glMaterialf(GL_F
}
if (!IsVis) goto EndVisible_label
BYTE vbDrawMode;
switch(mode)
{
case 0:
vbDrawMode = m_ucMode&0x0f;
break;
case 1:
vbDrawMode = DCGOBJ_EDGES;
break;
}
switch(vbDrawMod
{
case 0:
case DCGOBJ_FACES: // draw faces
{
int vi;
if (hasTexture==0 /*|| !(m_ucMode&DCGOB
{
glDisable(GL_TEX
for(vi=0;vi<m_pr
{
glBegin(GL_TRIAN
glVertex3f(verte
glVertex3f(verte
glVertex3f(verte
glEnd();
}
}
else
{
if (m_prop[2])
{
glEnable(GL_TEXT
glTexImage2D(GL_
GL_UNSIGNED_BYTE
glTexParameteri(
glTexParameteri(
glTexParameteri(
glTexParameteri(
glTexEnvi(GL_TEX
for(vi=0;vi<m_pr
{
glBegin(GL_TRIAN
glTexCoord2d(tex
glVertex3f(verte
glTexCoord2d(tex
glVertex3f(verte
glTexCoord2d(tex
glVertex3f(verte
glEnd();
}
}
}
}
break;
case DCGOBJ_EDGES:// draw edges
{
int vi;
for(vi=0;vi<m_pr
{
glBegin(GL_LINE_
glVertex3f(verte
glVertex3f(verte
glVertex3f(verte
glEnd();
}
}
break;
case DCGOBJ_VERTEX: // draw points
{
int vi;
for(vi=0;vi<m_pr
{
glBegin(GL_POINT
glVertex3f(verte
glVertex3f(verte
glVertex3f(verte
glEnd();
}
}
break;
}
EndVisible_label
if (hasMaterial==0) glDisable(GL_COL
else glEnable(GL_COLO
stop_draw_obj:
;
}
void dcGObject::SaveA
{
FILE *outf;
CString vstr;
char buf[512];
char odoa[2]={0x0d,0x
int vi,vs;
outf = fopen(sFilename,
if (!outf) goto error_label;
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(«Pro
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(«has
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(«Mod
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(«Col
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(«has
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(» Ambient R:%f G:%f B:%f»,ambient[0]
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(» Diffuse R:%f G:%f B:%f»,diffuse[0]
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(» Specular R:%f G:%f B:%f»,specular[0
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vstr.Format(» Shininess %f»,shininess);
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vs = m_prop[0];
for(vi=0;vi<vs;v
{
vstr.Format(«%f %f %f»,vertex[vi*3]
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
}
fwrite(&odoa,2,1
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vs = m_prop[1];
for(vi=0;vi<vs;v
{
vstr.Format(«%d %d %d»,faces[vi*3],
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
}
fwrite(&odoa,2,1
if (m_prop[2])
{
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
vs = m_prop[0];
for(vi=0;vi<vs;v
{
vstr.Format(«%f %f»,texvert[vi*2
ZeroMemory(buf,5
fwrite(&buf,strl
fwrite(&odoa,2,1
}
}
fclose(outf);
error_label:
;
}
////////////////
////////////////
//
void dcGObject::opera
{
int vi, vs;
RemoveArrays();
//src.SaveArrays
m_sObjName.Empty
m_sObjName = src.m_sObjName;
m_ucMode = src.m_ucMode;
m_bType = src.m_bType;
m_fFparam1 = src.m_fFparam1;
m_prop[0] = src.m_prop[0];m_
vs = src.m_prop[0]*3; vertex = new GLfloat[vs];
/*CString vstr;
vstr.Format(«%d %d»,vs,src.m_pro
MessageBox(0,vst
//for(int i=0;i<vs;i++)ver
memcpy(vertex,sr
vs = src.m_prop[1]*3; faces = new GLint[vs];
//for(int j=0;j<vs;j++)fac
memcpy(faces,src
//vs = sizeof(src.mask)
//memcpy(mask,sr
//for(vi=0;vi<vs
color[0] = src.color[0];col
color[3] = src.color[3];
dx = src.dx;dy = src.dy;dz = src.dz;
rx = src.rx;ry = src.ry;rz = src.rz;
sx = src.sx;sy = src.sy;sz = src.sz;
#ifdef DCGOBJ_FLIP_AND_
memcpy(m_fShift,
memcpy(m_bFlip,s
#endif
hasMaterial = src.hasMaterial;
shininess = src.shininess;
for(vi=0;vi<4;vi
{
ambient [vi] = src.ambient [vi];
diffuse [vi] = src.diffuse [vi];
specular[vi] = src.specular[vi]
}
hasTexture = src.hasTexture;
dTexX = src.dTexX; dTexY = src.dTexY;
dTexIndex = src.dTexIndex;
dTexInvMode = src.dTexInvMode;
if (src.m_prop[2])
{
vs =src.m_prop[0]*2
memcpy(texvert,s
}
//for(int k=0;k<vs;k++)tex
//SaveArrays(«eq
vs = src.m_aObjects.G
m_aObjects.SetSi
for(vi=0;vi<vs;v
m_aObjects[vi] = src.m_aObjects[v
}