Приветствую Вас Гость | Зарегистрироваться | Вход | RSS

Поиск по сайту:
Поиск в интернете:
Главная » Статьи » Учебники по Blitz3d

Создание ландшафтов с применением алгоритма ROAM(Vol 1)
1.Введение
Алгоритм ROAM (Real-time Optimally Adapting Meshes), основанный на структуре "Бинарное дерево треугольников", представляет Duchaineau et.al. и был реализован в движке Tread Marks (http://www.TreadMarks.com). Я не претендую на 100% достоверную передачу алгоритма, но постарался оптимизировать по своему усмотрению и добавил некоторые моменты, которые нельзя реализовать штатными средствами в блице (например, отрисовка группы треугольников). Добавленные или измененные мною моменты выделены в статье. Хотелось бы сразу отметить что пример не показывает обновляющийся в реалтайме террайн, а просто демонстрирует механизм работы алгоритма. Скорость блица не позволит сделать террайн обновляющийся каждый кадр быстрее чем встроенный в Блиц3д. Алгоритм ROAM довольно труден для восприятия и поэтому я постарался максимально подробно объяснить каждое действие и максимально иллюстрировать документ наглядным материалом.
2.Сущность ROAM метода
2.1 Основные понятия
Для построения ландшафта нам необходима карта высот. В нашем случае это будет массив вещественных чисел HeightMap#(TerrainSize,TerrainSize) , считанный из изображения. Ключевым понятием в методе ROAM является прямоугольный треугольник. Давайте рассмотрим его структуру:

Рассматриваемый треугольник образован тремя вершинами: левый вертекс (v0), вертекс верхушки (v1) и правый вертекс (v2). На середине расстояния между боковыми точками поставим точку и назовем её центральной точкой (vC). Если провести линию от вертекса верхушки к центральной точке, то мы разделим исходный треугольник на два дочерних: левый и правый потомки. Исходный треугольник при этом будет являться для них родительским. Каждый из полученных треугольников можно разделить точно так же. Таким образом, деля треугольники до определенного уровня мы можем детализировать ландшафт настолько насколько это необходимо:

Важным моментом является понятие соседа основания (base neighbor) - это тот треугольник, который своим основанием прилежит к основанию рассматриваемого треугольника.
2.2.Деление треугольников

Теперь рассмотрим, по какому принципу происходит деление родительского треугольника на дочерние. Чтобы узнать необходимо ли нам разбивать треугольник, нужно определить насколько форма описываемвая треугольником отличается от фактической высоты по HeightMap'е. Рассмотрим треугольник. В качестве эталонной точки берется центральная точка. Погрешность вычисляется по очень простой формуле:

погрешность=Abs((hLeft+hRight)/2-hCenter)
hLeft,hRight - это высота по карте высот в точках правого и левого вертекса.
hCenter - это высота по карте высот центральной точке
(hLeft+hRight)/2 - интерполированная высота над центральной точкой

Например, возьмем hLeft=15.0, hRight=25.0 и hCenter=23.0. По формуле погрешность равна Abs((15+25)/2-23)=Abs(20-23)=3. Чтобы определить является ли погрешность достаточной для деления, нам понадобится переменная, назовём её RoamMaxHeightError. Её значение характеризует максимально допустимую разницу высот между фактической и желаемой. Чем меньше её значение, тем больше ландшафт будет соответствовать действительности и тем больше рисовать полигонов. И наоборот чем больше её значение, тем грубее будет ландшафт и тем меньше полигонов занимать. Если принять RoamMaxHeightError=5, то треугольник дальше разбиваться не будет, т.к. погрешность< RoamMaxHeightError (3<5). Если же принять значение RoamMaxHeightError=2, то треугольник будет разбит, т.к. погрешность превышает максимально допутимый уровень погрешности (3>2). Для примера покажу несколько рендеров ландшафта 1024*1024 с разным значением RoamMaxHeightError. Высота ландшафта от -40.96 до 40.96.


Рисунок RoamMaxHeightError Количество полигонов
2.1 10.0 323
2.2 2.0 5032
2.3 0.75 25348

Здесь наглядно видно преимущество метода: треугольники не тратятся на отрисовку относительно плоских поверхностей, а более детально обрабатывают выпуклые поверхности.
2.3.Бинарное дерево
Теперь разберемся, почему алгоритм основан на структуре "Бинарное дерево треугольников". Как видно из предыдущей картинки каждый треугольник имеет свой индивидуальный номер. Левому потомку присваивается номер (родитель<<1), а правому (родитель<<1)+1.

Структура ландшафта в памяти компьютера представлена банком памяти, при этом каждому треугольнику соответствует байт памяти, а его адрес соответствует номеру треугольника. Значение байта представляет будет ли делиться треугольник. Например, значение 1 обозначает, что текущий треугольник будет разделен на два дочерних, а значение 0 что не будет. Бинарное дерево даёт преимущество в том, что адрес каждого треугольника очень легко вычислить, используя операции байтового сдвига. Сдвиг вправо дает возможность найти родителя:

parent = Tri Shr 1

а сдвиг влево потомков:

LeftChild =Tri Shl 1
RightChild =(Tri Shl 1)+1;

Таким образом алгоритм построения ландшафта складывается из двух частей:

  1. Сначала мы рекурсивно обходим треугольники, проверяя погрешность высоты. Если погрешность превышает RoamMaxHeightError то записываем в соответствующий байт в банке памяти 1 и проверяем погрешность высоты для его потомков (для них аналогично). Если же погрешность укладывается в RoamMaxHeightError то записываем в соответствующий байт 0 и переходим к следующему шагу.
  2. Теперь строим меш ландшафта по созданному нами дереву.
2.4.Diamond split
Однако даже в таком простом и наглядном алгоритме есть одна проблема. Давайте рассмотрим на примере:

У нас есть треугольник. Рассмотрим процесс его деления по шагам.

  1. Имеется треугольник 1. Определяем погрешность, допустим она больше текущего RoamMaxHeightError. Поэтому разделяем его на два дочерних: 2 и 3
  2. Рассматриваем треугольники 2 и 3. Допустим погрешность в треугольнике 3 не больше RoamMaxHeightError и поэтому дальше его не делим. Теперь допустим, что погрешность в треугольнике 2 достаточна для его деления на треугольники 4 и 5.
  3. Треугольник 3 не имеет потомков, его структура дальше не просчитывается. Теперь рассматриваем треугольники 4 и 5. Допустим, дальше треугольник 5 остается без изменений, а 4 делится на 8 и 9.
  4. В итоге мы имеем поверхность, состоящую из треугольников 3,5,8,9. Обратим внимание на стык треугольников 3, 8 и 9. Как видно 8 и 9 представляют участки с большей детализацией и 3 с меньшей. Из за этого на поверхности ландшафта будут образовываться так называемые трещины. Вот как они выглядят:

Описанная ситуация решается довольно просто. Помните, в описании структур мы говорили и понятии "соседа основания "? Для того чтобы устранить зазор в поверхности необходимо разделить и соседа основания. В оригинальном документе два прилежащих основаниями треугольника называют Diamond, из-за похожести его на алмаз или бриллиант. А операция по их делению называется Split on a diamond, то есть его разделение. После того как сосед основания будет разделен, алгоритм переходит на его родителя и его соседа основания. И так до тех пор, пока не встретятся уже оба разделенных треугольника.


Источник: http://madmedic.by.ru/art03.htm
Категория: Учебники по Blitz3d | Добавил: blitz3d-portal (08.Декабрь.06) E W
Просмотров: 6215 | Комментарии: 1 | Рейтинг: 2.3/3
Всего комментариев: 1
1 blitz3d-portal  
0
Ой какие мы жадные
Надо со всеми делиться!!

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]