Задание 3 (1124483), страница 2
Текст из файла (страница 2)
При заменецилиндра на конус, а овального листа на кленовый лист, код модели меняться не долженпри соблюдении ограничений на примитивы.Ограничения на примитивы: ветка или лист - вертикально расположенный объект длины1, симметричный относительно оси y. Ширина и глубина объекта могут быть любыми.Не обязательно в точности реализовывать описанную ниже модель. Можно дополнять её иизменять. Главное требование - получить похожий на дерево результат! Однако в моделидолжна быть некоторая вариативность, как и в природе, то есть задавать строгуюрекурсивную структуру с фиксированными параметрами нельзя.Рост дерева начинается с корневого элемента (ствола). На каждом шаге имеющиесяэлементы изменяются (увеличиваются) и добавляются новые.Характеристики узлаУ каждого узла дерева должна быть следующая информация:указатель на родительский элементуказатели на всех потомковУ узла-ветки бывают потомки двух типов: ветки и листья.
У узла-листа не бываетпотомков. Кроме этого, должен быть набор параметров, по которым на каждом шаге ростапересчитывается модельная матрица, которую нужно использовать для визуализации вдальнейшем.1. Положение и направление. Удобно задавать их относительно родительской ветки.Тогда положение будет задаваться следующими параметрами:высота на родительской ветке (от 0 до 1)отклонение от ветки в родительской плоскости xy (от - 180 до 180 градусов)отклонение вокруг родительской оси y (от 0 до 360 градусов).На каждый из этих параметров наложим некоторые ограничения для того, чтобы деревобыло похоже на настоящее, а не на произвольную структуру.Высота на родительской ветке. Желательно, чтобы ветки и листья располагались болееменее равномерно, но всё же случайным образом.
Предлагается поступить так: выделитьмаксимально допустимое число слотов на ветки и листья. При добавлении новой веткиразрешать помещать её в произвольное место произвольного свободного слота.Отклонение от ветки в родительской плоскоскости xy. Если разрешить ветвиться повсему теоретическому диапазону возможных углов (от -180 до 180), то ветки будут растихаотически (см. рис.
слева). Поэтому нужно регламентировать допустимые углы. Какминимум, нужно ограничить разброс углов веток некоторым максимальным значением.Можно также ограничить минимальное значение, чтобы ветки не прижимались близкодруг к другу (избежать ситуации на рис. по центру).Кроме того, хотелось бы в принципе избежать того, чтобы ветви росли вниз. Т.е.наложить ограничения не только угол относительно родительской ветки, но и на полныйрезультирующий угол. Для того чтобы это сделать, необходимо сделать возможностьрасчета результирующего угла в пространстве модели всех веток (т.е. в пространствекорневого элемента). Предположим, что для всех родительских веток уже правильнорассчитаны модельные матрицы.
Тогда требуется:1. Узнать у родительского элемента его угол в модельных координатах (из модельнойматрицы).2. Сложить этот угол с относительным углом.После этого: если результирующий угол оказался больше X градусов или меньше -Xградусов (ветка идет ниже горизонтали), скорректировать его. Например, можно поменятьзнак у относительного угла (см. рис.).
X можно выбрать равным, допустим 120 градусам.Можно сделать более корректный выбор, проверяя не только угол родительской ветки, нои абсолютное положение начала ветки. Если ветка генерируется слишком низко, неразрешать ей угол ниже 90 градусов.Для листьев проводить подобные проверки не обязательно в силу того, что листья нестанут увеличивать ошибку за счет своих потомков.2.
Толщина и длина ветки - другая группа параметров. По мере прошествиявремени ветки становятся толще и длиннее, кроме того, дочерняя ветка должнабыть всегда не шире и не длиннее родительской.Листья могут быть статическими (не изменять размеры с прошествием времени), могуттакже не зависеть от величины родительской ветки, а могут и изменяться. В любомслучае, реализовав оба механизма над ветками, вы можете просто продублировать их длялистьев, поэтому далее я буду говорить только о ветках.1.
Во-первых, некоторое масштабирование может быть задано извне модели для всехветок или всех листьев целиком. Например, листья должны быть меньше веток, аветка должна быть узким цилиндром, а не толстым.2. Во-вторых, на каждом шаге роста эти параметры должны увеличиваться нанекоторый %.3. В-третьих, при задании длины и ширины дочерней ветки должен использоватьсяещё и коэффициент масштабирования относительно родительской ветки.Например, реализация может быть такой. Храним внутри каждого узла переменную,соответствующую времени его жизни.
Каждый раз, когда дерево растет, эта переменнаяво всех существующих узлах увеличивается на 1.Текущий размер ветки рассчитывается следующим образом:float l = m_fLength*(1+m_fIncreaseLengthStep*m_iTime);float w = m_fWidth*(1+m_fIncreaseWidthStep*m_iTime);m_fIncreaseLengthStep, m_fIncreaseWidthStep прямо-пропорционально связаны с периодомдобавления новых узлов (см. в разделе “Характеристики дерева”) коэффициентами,которые лучше подобрать самим.m_fLength и m_fWidth задаются при создании узла и состоят из двух множителей:коэффициент для всех объектов этого типа и коэффициент масштабированияотносительно родителя.m_fLength = pParent->m_fLength*m_fChildBranchLengthCoeffm_fWidth = pParent->m_fWidth*m_fChildBranchWidthCoeffm_fChildBranchLengthCoeff и m_fChildBranchWidthCoeff можно брать в пределах от 0.5 до1.0.Характеристики дереваДерево - это структура, которая создает узлы, рассчитывает параметры генерации,координирует узлы, назначает родителей и потомков, а также предоставляет интерфейсдля основного приложения.Во-первых, дерево хранит в себе массив указателей на узлы (ветки и листья).
Дляпростоты можно ограничить максимальное число веток и листьев в дереве и выделить дляуказателей для них память при создании объекта.Во-вторых, дерево хранит в себе все возможные параметры модели, то есть в том численекоторые параметры узла, которые передает ему при создании.
Кроме группыпараметров для веток и группы параметры для листьев, дерево также ведет учет временижизни модели (т.е. времени жизни ствола).Обновление модели можно выполнять в 2 шага:рост существующих ветокдобавление новыхПри этом рост существующих веток можно производить чаще, чем добавление новых(особенно это важно для тех, кто делает анимированный рост дерева). Добавление новыхосуществляется раз в несколько тактов роста. Это значение будем называть периодомдобавления новых узлов.
Если узлы добавляются на каждом шаге (если вы не делаетеанимацию), то период добавления узлов равна 1, иначе он больше.Также добавление новых узлов можно ограничить максимальным значением шагов, послекоторого ветви только удлиняются и утолщаются.Алгоритм роста1 Этап. Класс дерева.Если общее число шагов меньше максимального.- Рост всегда (на каждом шаге построения модели) начинается со ствола. Если ствол несуществует, то инициализируем его характеристики, создаем, устанавливаем указатель народителя равным 0.- Передаем стволу команду “Рост” (вызываем его метод).- Обновляем глобальный счетчик времени.2.
Узел. “Рост”.- Обновляем значение модельной матрицы. Вызываем рост у всех потомков (рекурсия).- Если есть свободные слоты, просим дерево добавить новые ветки и новые листья.- Обновляем локальный счетчик времени.3. Дерево. “Добавление новых элементов”. Этот метод вызвал какой-то узел и передалсебя в качестве параметра.Если в массиве ещё есть место, то создаем новую ветку (или лист).
Передаем ейпараметры (которые задал пользователь) и адрес родителя (того, который вызвал метод).Обновление значений модельной матрицы по предрассчитанным параметрам1. Получаем абсолютный угол родителя и абсолютное положение точки, из которой растетданный узел.2. Добавляем к полученным у родителя значениям собственные и проводим простыегеометрические преобразования (масштабирование, вращение вокруг оси z, вращениевокруг оси y, сдвиг). Разрешается использовать средства библиотеки glm для генерацииотдельных матриц на каждую операцию.Алгоритм получения абсолютных значений параметров ветки по рассчитаннойматрицеПредположим, что текущая ветка имеет локальную высоту h и локальные углы a,b.
Мызнаем, что до модельного преобразования родительская ветка была строго вертикальна идлиной была 1. Значит, чтобы, к примеру, найти её конец, нужно домножить модельнуюматрицу на вектор [0,1,0,1], а чтобы найти начало, на вектор [0,0,0,1]. Таким образом,направление ветки легко получить, домножив модельную матрицу на [0,1,0,0]. Получитьуглы можно простыми преобразованием из декартовой системы координат всферическую. А точка роста получается с помощью вектора [0,h,0,1].Визуализация моделиВизуализировать модель можно в 2 шага.