
Лабораторная работа №2 (растеризация треугольника)
.doc
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ
ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
ЛИПЕЦКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
КАФЕДРА АВТОМАТИЗИРОВАННЫХ СИСТЕМ УПРАВЛЕНИЯ
Лабораторная работа №2
по дисциплине
«Компьютерная графика»
на тему:
«Растеризация треугольника»
|
Студент |
|
|
|
Филатов А.А. |
|
||||||||
|
|
|
подпись, дата |
|
фамилия, инициалы |
|
||||||||
|
Группа |
|
АС-09-1 |
|
|
|
|
|||||||
|
|
|
|
|
|
|
||||||||
|
Принял |
|
|
|
|
|
||||||||
|
|
|
|
|
Назаркин О.А. |
|
||||||||
|
ученая степень, звание |
|
подпись, дата |
|
фамилия, инициалы |
|
Липецк 2010
1.Задание
Реализовать алгоритм растрирования треугольника, при условии, что вершины окрашены в разные цвета. Реализовать смешивание цветов внутри треугольника. Количество треугольников: 10.
2.Теория
Барицентрические
координаты —
координаты точки n-мерного аффинного
пространства An,
отнесенные к некоторой фиксированной
системе из (n + 1)-ой точки ,
не лежащих в (n − 1)-мерном
подпространстве.
Пусть z есть
произвольная точка в An. Каждая
точка может
быть единственным образом представлена
в виде суммы
где —
вещественные числа, удовлетворяющие
условию
Числа называются барицентрическими
координатами точки x. Легко видеть,
что барицентрические координаты не
зависят от выбора z.
Точка x является центром
тяжести масс ,
расположенных в точках
.
Формулы для расчета:
3.Алгоритм
Для одного треугольника:
1. Проверяем все пиксели, находятся они внутри треугольника или нет.
2. Вычисляются барицентрические координаты точки относительно вершин треугольника.
3. Определяем цвет пикселя исходя из цветов вершин и барицентрических координат и закрашиваем пиксель.
3. Пункты 1-3 выполняется 10 раз с другими параметрами (по количеству треугольников).
4.Листинг программы
#include <math.h>
#include <time.h>
#include <stdlib.h>
//параметры для преобразования координат из мировой системы координат в оконную
int width=1000;
int height=600;
int xmin=-width/2;
int xmax=width/2;
int ymin=-height/2;
int ymax=height/2;
int Xmax=width;
int Ymax=height;
//цвета
#define WHITE 0xFFFFFFFF
#define BLACK 0xFF000000
#define RED 0xFFFF0000
#define GREEN 0xFF00FF00
#define BLUE 0xFF0000FF
#define CYAN 0xFF00FFFF
#define MAGENTA 0xFFFF00FF
#define YELLOW 0xFFFFFF00
void Randomize()
{
srand(time(NULL));
}
int Random(int val)
{
return rand()%val;
}
struct Dot//пиксель
{
int x;
int y;
unsigned int color;
};
unsigned int ARGB(int a, int r, int g, int b)
{
if(a>255) a=255;
if(r>255) r=255;
if(g>255) g=255;
if(b>255) b=255;
return 0x00000000 | a<<24 | r<<16 | g<<8 | b;
}
unsigned int randomColor()
{
return 0xFF000000 | Random(255)<<16 | Random(255)<<8 | Random(255);
}
struct Dot randomDot(int sizeX,int sizeY)
{
struct Dot A;
A.x=Random(sizeX)-sizeX/2;
A.y=Random(sizeY)-sizeY/2;
A.color=ARGB(Random(256)+128,Random(256),Random(256),Random(256));
return A;
}
int Xs(int x)//перевод координаты х из мировой в оконную
{
return int(float(Xmax/(xmax-xmin))*(x-xmin));
}
int Ys(int y)//перевод координаты у из мировой в оконную
{
return int(Ymax-(y-ymin)*float(Ymax/(ymax-ymin)));
}
unsigned int AlphaBlend(const unsigned int bg, const unsigned int src)//альфа-наложение, bg - фон, src - пиксель
{
unsigned int a = src >> 24;
if(!a)
return bg;
unsigned int bg_r=(bg>>16)%256;
unsigned int bg_g=(bg>>8)%256;
unsigned int bg_b=(bg)%256;
unsigned int src_r=(src>>16)%256;
unsigned int src_g=(src>>8)%256;
unsigned int src_b=(src)%256;
int r=int(bg_r*double((255-a)/255.)+src_r*double(a/255.));
int g=int(bg_g*double((255-a)/255.)+src_g*double(a/255.));
int b=int(bg_b*double((255-a)/255.)+src_b*double(a/255.));
if(r>255) r=255;
if(g>255) g=255;
if(b>255) b=255;
return 0xFF000000 | r<<16 | g<<8 | b;
}
unsigned int Blending(unsigned int color1,unsigned int color2,unsigned int color3)//смешивание трех цветов
{
int a1=color1>>24;
int a2=color2>>24;
int a3=color3>>24;
int r1=(color1>>16)%256,g1=(color1>>8)%256,b1=color1%256;
int r2=(color2>>16)%256,g2=(color2>>8)%256,b2=color2%256;
int r3=(color3>>16)%256,g3=(color3>>8)%256,b3=color3%256;
int a=a1+a2+a3;
int r=int(r1*double(a1/255.)+r2*double(a2/255.)+r3*double(a3/255.));
int g=int(g1*double(a1/255.)+g2*double(a2/255.)+g3*double(a3/255.));
int b=int(b1*double(a1/255.)+b2*double(a2/255.)+b3*double(a3/255.));
if(a>255) a=255;
if(r>255) r=255;
if(g>255) g=255;
if(b>255) b=255;
return 0x00000000 | a<<24 | r<<16 | g<<8 | b;
}
unsigned int AlphaColor(unsigned int color, int alpha)//возврат цвета color с прозрачностью alpha
{
int r=(color>>16)%256,g=(color>>8)%256,b=color%256;
if(alpha>255) alpha=255;
//alpha=255-alpha;
return 0x00000000 | alpha<<24 | r<<16 | g<<8 | b;
}
bool IdenticalSignTriangle(struct Dot A,struct Dot B,struct Dot C,struct Dot D)//проверка, лежат ли точки С и D по одну сторону прямой АВ
{
double p1=double(B.y-A.y)/double(B.x-A.x)*double(C.x-A.x)-double(C.y-A.y);
double p2=double(B.y-A.y)/double(B.x-A.x)*double(D.x-A.x)-double(D.y-A.y);
if((p1>0 && p2>0) || (p1<=0 && p2<=0))
return true;
return false;
}
bool BelongTriangleLine(struct Dot A,struct Dot B,struct Dot C,struct Dot D)//проверка принадлежности точки треугольнику
{
if(IdenticalSignTriangle(A,B,C,D) && IdenticalSignTriangle(C,A,B,D) && IdenticalSignTriangle(B,C,A,D))
return true;
return false;
}
double distDotLine(struct Dot A,struct Dot B,struct Dot D)//расстояние от точки D до прямой АВ (по перпендикуляру)
{
double a=B.y-A.y;
double b=A.x-B.x;
double c=A.x*(A.y-B.y)+A.y*(B.x-A.x);
return abs((a*D.x+b*D.y+c)/sqrt(a*a+b*b));
}
void drawTriangle(unsigned int *pDest, struct Dot A,struct Dot B,struct Dot C)//рисование треугольника с вершинами А,В,С в массиве pDest
{
int x,y;
struct Dot D;
double pa, pb, pc;
for(y=ymax;y>ymin;y--)
for(x=xmin;x<xmax;x++)
{
D.x=x;
D.y=y;
pa=double((B.y-C.y)*(D.x-C.x)+(C.x-B.x)*(D.y-C.y))/double((B.y-C.y)*(A.x-C.x)+(C.x-B.x)*(A.y-C.y));
pb=double((C.y-A.y)*(D.x-C.x)+(A.x-C.x)*(D.y-C.y))/double((C.y-A.y)*(B.x-C.x)+(A.x-C.x)*(B.y-C.y));
pc=1-pa-pb;
if(BelongTriangleLine(A,B,C,D))
{
D.color=Blending(AlphaColor(A.color,int(pa*255.)),AlphaColor(B.color,int(pb*255.)),AlphaColor(C.color,int(pc*255.)));
pDest[Ys(y)*width+Xs(x)]=D.color;
}
}
}
struct Dot createDot(int x,int y,unsigned int color)//возвращает заполненную структуру (подобие конструктора)
{
struct Dot A;
A.x=x;
A.y=y;
A.color=color;
return A;
}
void FillData(void *data, int Width, int Height)//функция рисование шести треугольников
{
width=Width;
height=Height;
unsigned int* pDest = (unsigned int*)data;
unsigned int background=0xFFFFFFFF;
for(int y=ymax;y>ymin;y--)
for(int x=xmin;x<xmax;x++)
{
pDest[Ys(y)*width+Xs(x)]=background;
if(!x || !y)
pDest[Ys(y)*width+Xs(x)]=0xFF888888;
}
drawTriangle(pDest,createDot(0,0,WHITE),createDot(0,200,RED),createDot(150,100,YELLOW));
drawTriangle(pDest,createDot(0,0,WHITE),createDot(150,100,YELLOW),createDot(150,-100,GREEN));
drawTriangle(pDest,createDot(0,0,WHITE),createDot(150,-100,GREEN),createDot(0,-200,CYAN));
drawTriangle(pDest,createDot(0,0,WHITE),createDot(1,-200,CYAN),createDot(-150,-100,BLUE));
drawTriangle(pDest,createDot(0,0,WHITE),createDot(-150,-100,BLUE),createDot(-150,100,MAGENTA));
drawTriangle(pDest,createDot(0,0,WHITE),createDot(-150,100,MAGENTA),createDot(1,200,RED));
Randomize();
drawTriangle(pDest,createDot(-500,300,randomColor()),createDot(-50,250,randomColor()),createDot(-450,10,randomColor()));
drawTriangle(pDest,createDot(500,300,randomColor()),createDot(50,250,randomColor()),createDot(450,10,randomColor()));
drawTriangle(pDest,createDot(-500,-300,randomColor()),createDot(-50,-250,randomColor()),createDot(-450,-10,randomColor()));
drawTriangle(pDest,createDot(500,-300,randomColor()),createDot(50,-250,randomColor()),createDot(450,-10,randomColor()));
}
5.Контрольный пример