Одним из важнейших алгоритмов растеризации является алгоритм растеризации треугольника (заполнения треугольника), т.к. в большинстве моделей построения трехмерных объектов последние состоят именно из треугольников. В некоторых статьях этот алгоритм называется алгоритм рисования треугольника. Схематично алгоритм можно описать следующим образом:
Треугольник разбивается на две части вертикальной линией, проходящей через среднюю точку. Каждый из двух полученных треугольников растеризуется по отдельности. В процессе растеризации обе стороны растеризуются параллельно, таким образом, чтобы координаты по оси Y текущих точек на обоих отрезках совпадали. При этом связность растеризуемых линий (сторон треугольника) не обеспечивается. При получении координат текущих точек горизонтальный отрезок между ними заполняется.
#include <windows.h> #include "math.h" #include "fixed.h" #define roundf(x) floor(x + 0.5f) inline void swap(int &a, int &b) { int t; t = a; a = b; b = t; } void triangle(HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3) { // Упорядочиваем точки p1(x1, y1), // p2(x2, y2), p3(x3, y3) if (y2 < y1) { swap(y1, y2); swap(x1, x2); } // точки p1, p2 упорядочены if (y3 < y1) { swap(y1, y3); swap(x1, x3); } // точки p1, p3 упорядочены // теперь p1 самая верхняя // осталось упорядочить p2 и p3 if (y2 > y3) { swap(y2, y3); swap(x2, x3); } // приращения по оси x для трёх сторон // треугольника fixed dx13 = 0, dx12 = 0, dx23 = 0; // вычисляем приращения // в случае, если ординаты двух точек // совпадают, приращения // полагаются равными нулю if (y3 != y1) { dx13 = int_to_fixed(x3 - x1); dx13 /= y3 - y1; } else { dx13 = 0; } if (y2 != y1) { dx12 = int_to_fixed(x2 - x1); dx12 /= (y2 - y1); } else { dx12 = 0; } if (y3 != y2) { dx23 = int_to_fixed(x3 - x2); dx23 /= (y3 - y2); } else { dx23 = 0; } // "рабочие точки" // изначально они находятся в верхней точке fixed wx1 = int_to_fixed(x1); fixed wx2 = wx1; // сохраняем приращение dx13 в другой переменной int _dx13 = dx13; // упорядочиваем приращения таким образом, чтобы // в процессе работы алгоритмы // точка wx1 была всегда левее wx2 if (dx13 > dx12) { swap(dx13, dx12); } // растеризуем верхний полутреугольник for (int i = y1; i < y2; i++){ // рисуем горизонтальную линию между рабочими // точками for (int j = fixed_to_int(wx1); j <= fixed_to_int(wx2); j++){ SetPixel(hdc, j, i, 0); } wx1 += dx13; wx2 += dx12; } // вырожденный случай, когда верхнего полутреугольника нет // надо разнести рабочие точки по оси x, т.к. изначально они совпадают if (y1 == y2){ wx1 = int_to_fixed(x1); wx2 = int_to_fixed(x2); } // упорядочиваем приращения // (используем сохраненное приращение) if (_dx13 < dx23) { swap(_dx13, dx23); } // растеризуем нижний полутреугольник for (int i = y2; i <= y3; i++){ // рисуем горизонтальную линию между рабочими // точками for (int j = fixed_to_int(wx1); j <= fixed_to_int(wx2); j++){ SetPixel(hdc, j, i, 0); } wx1 += _dx13; wx2 += dx23; } }
Прикрепленный файл | Размер |
---|---|
Исходный код | 3.81 кб |
Исполняемый файл | 4.54 кб |