Лекции по компьютерной графике
.pdfКлиментьев К.Е. Компьютерная графика (курс лекций).
Индивидуальные задания по теме “Алгоритмы построения и преобразования изображений”
1.Вращение и масштабирование фрагмента штрихового изображения
2.Перевод полутонового изображения в “серую гамму” и выделение контуров в режиме
3.Перевод полутонового изображения в “серую гамму” и последовательные матричные операции: 1) размывка контуров; 2) увеличение резкости.
4.Вращение “проволочной” фигуры (линии которой построены при помощи алгоритма Брезенхама) в плоскостях, перпендикулярных плоскости экрана.
5.Вращение символов 8х8 в плоскости экрана относительно заданного центра
6.Вращение “проволочной” фигуры в плоскости экрана
7.Наложение полутоновой текстуры на треугольник и вращение в плоскости экрана.
8.Наложение полутоновой текстуры на треугольник и вращение в плоскостях, перпендикулярных плоскости экрана.
9.Построение множества случайно расположенных окружностей и замкнутых четырехугольников, границы которых построены при помощи алгоритма Брезенхама и “заливка” получившихся замкнутых фигур при помощи рекурсивного алгоритма со случайной “затравкой”.
10.Построение объемного “проволочного” куба при помощи алгоритма Брезенхама и вращение его в плоскостях, перпендикулярных плоскости экрана.
11.Построение случайного лабиринта, линии которого построены при помощи алгоритма Брезенхама и обход его рекурсивным алгоритмом.
12.Построение “фигур Лиссажу” и заливка каждого сегмента отдельным цветом рекурсивным алгоритмом с затравкой.
13.Построение изображения “коридора”, стены и потолок которого покрыты полутоновыми текстурами
14.Перевод полутонового цветного изображения в “серую” гамму, загрязнение его случайно расположенных пятен и “очистка” при помощи матричного фильтра.
15.Вращающееся звездное небо.
16.“Лупа”. Масштабирование круглого фрагмента штрихового изображения.
17.Трансформации небольшого полутонового изображения: масштабирование, перемещение, вращение в плоскости экрана, симметричное отражение
18.“Спрайты”: перемещение небольшого изображения поверх другого.
19.Вращение фрагмента полутонового изображения в плоскости, перпендикулярной плоскости экрана
20.“Лупа”. Масштабирование фрагмента полутонового изображения.
Примечание. Лабораторная работа выполняется в операционной системе MS-DOS (возможно использование DOS-сессии операционных систем Windows 95/98/ME). Языки программирования: Pascal или C, рекомендуемые системы программирования: Turbo Pascal v6.0/7.0 и Borland C/C++ v3.1. Применение расширенных возможностей языка С++
(классов, перегруженных операторов и т.п.), а также использование языка ассемблера не допускается. Если не указано иное, то работа выполняется в графическом режиме
320x200x256.
51
Климентьев К.Е. Компьютерная графика (курс лекций).
Индивидуальные задания по теме “Программирование трехмерных изображений”
Вариант |
ОреnGL |
Win API |
|
|
|
|
|
1 |
Бильярдный стол с шарами |
Шар |
|
2 |
Шахматная доска с фигурами |
Круглая буханка хлеба |
|
3 |
Бусы из разноцветных камней на |
Яйцо |
|
|
подоконнике |
|
|
4 |
Египет: пирамиды и пальмы |
Огурец |
|
|
|
|
|
5 |
Сатурн с кольцами и спутниками |
Капля |
|
6 |
Футбольное поле с мячом |
Груша |
|
7 |
Елка с шарами |
Головка чеснока |
|
8 |
Самовар на столе |
Цилиндр |
|
9 |
Натюрморт на столе: яблоки, томаты и |
Конус |
|
|
корнишоны. |
|
|
10 |
Яблоко и червяк |
Урна |
|
11 |
Снеговик зимой |
Ваза |
|
12 |
Сигарета в круглой пепельнице на столе |
Тор |
|
13 |
Пятачок с воздушным шариком |
Спираль |
|
14 |
Винни Пух с горшочком меда |
Куб |
|
15 |
Одуванчики на лугу |
Тетраэдр |
|
16 |
Чебурашка с флажком |
Усеченный конус |
|
17 |
Робот с лопатой |
Юла |
|
18 |
Коробок а столе с рассыпанными |
Октаэдр |
|
|
спичками |
|
|
19 |
Бутылка с рюмками на столе |
Трехгранная призма |
|
20 |
Домик и деревья |
Пятигранная призма |
|
21 |
Сад с яблонями и грибами |
Пистолетная пуля |
|
22 |
Аист с младенцем в небе |
Винтовочная пуля |
|
23 |
Конфеты и чупа-чупсы на столе |
Ромбовидная четырехгранная призма |
|
24 |
Воздушный шар в небе с облаками |
Дельтовидная |
четырехгранная |
|
|
призма |
|
25 |
Ракета в космосе |
Половинка цилиндра |
|
Примечание. Лабораторная работа выполняется в операционной системе Windows с использованием Win32 API, а также стандартных библиотек DirectX (DirectDraw) и OpenGL. Изображение должно состоять из объемных геометрических фигур, с учетом перспективы и однотонного освещения. Языки программирования: C или Object Pascal. Рекомендуемые системы программирования: Borland C/C++ v5.0, Borland C/C++ Builder, MS Visual C/C++ v 6.0, допускается использование Borland/Inprise Delphi. Применение языка ассемблера не допускается. Если не указано иное, то графическим режимом по умолчанию является
800x600x256.
52
Климентьев К.Е. Компьютерная графика (курс лекций).
Задание по теме “Средства работы с графикой”
Создать HTML-страницу на тему “Про себя - любимого (-мую)”. Составляется на русском языке в кодировке Win-1251 и должна обязательно использовать следующие возможности:
•заголовки разных уровней вложенности;
•текстовые абзацы (параграфы);
•жесткий разрыв строки;
•горизонтальную разделительную линию;
•пронумерованный или ненумерованный список;
•изменение стилей текста: курсив, жирный, подчеркивание;
•предварительно отформатированный текст;
•центрированный фрагмент текста;
•подстрочный (или надстрочный) индекс;
•изменение размера шрифта;
•измерение цвета шрифта;
•изменение вида шрифта;
•“запрещенные” символы: <, >, ”, & и т.п.;
•таблицы;
•масштабированные изображения;
•ссылки на другие HTML-документы или в другую позицию текущего документа;
•изменение цвета фона;
•использование изображений в качестве фона.
Использование JavaScript-апплетов и прочих скриптов, таблиц стилей и форм вводавывода не допускается.
53
Климентьев К.Е. Компьютерная графика (курс лекций).
Примеры программ, демонстрирующих алгоритмы 2D- и 3D-графики
Вывод точки реализован в MS-DOS через BIOS, все остальное сделано полностью самостоятельно.
Вариант на Си.
#include <dos.h> #include <math.h> #include <stdio.h>
/*
Установить новый видеорежим:
380x25x16
4320x200x4 0x12 640x480x16 0x13 320x200x256 */
setvmode(unsigned char m) { union REGS r1; struct SREGS r2; r1.h.al=m;
r1.h.ah=0;
int86x(0x10, &r1, &r1, &r2);
}
/* Нарисовать точку цвета c в координатах x/y */ setpoint( int x, int y, unsigned char c) {
union REGS r1; struct SREGS r2; r1.h.ah=0xC;
r1.h.al=c;
r1.h.bh=0;
r1.x.cx=x;
r1.x.dx=y;
int86x(0x10, &r1, &r1, &r2);
}
/* Вспомогательные процедурки для рисования треугольника */ swap( int* x, int* y) { int tmp; tmp = *x; *x = *y; *y = tmp; } int countx(int x1,int y1,int x2,int y2,int yy)
{return x1+((yy-y1)*(x2-x1))/(y2-y1);}
/* Рисование треугольника */
triang(int xa, int ya, int xb, int yb, int xc, int yc, int c) { int x, y, x3, x4;
if (yc<yb) { swap(&xc, &xb); swap(&yc, &yb); } if (yc<ya) { swap(&xc, &xa); swap(&yc, &ya); } if (yb<ya) { swap(&xb, &xa); swap(&yb, &ya); } for(y=ya;y<yc;y++) {
if (y<yb) {
x3 = countx(xa, ya, xc, yc, y);
x4 = countx(xa, ya, xb, yb, y); if (x4<x3) swap(&x3, &x4);
for (x=x3;x<x4;x++) setpoint(x,y,c);
}
else {
x3 = countx(xa, ya, xc, yc, y);
x4 = countx(xb, yb, xc, yc, y); if (x4<x3) swap(&x3, &x4);
for (x=x3;x<x4;x++) setpoint(x,y,c);
}
}
}
#define XYZ struct xyz XYZ { double x, y, z; };
/*Расчет новых 3-мерных координат для точки, повернутой на углы alfa и beta*/ XYZ Rotate( XYZ t, double alfa, double beta) {
54
Климентьев К.Е. Компьютерная графика (курс лекций).
XYZ tmp;
alfa = alfa * (3.141592/180.); beta = beta * (3.141592/180.);
tmp.x = t.x*cos(alfa) - t.y*sin(alfa);
tmp.y = t.x*sin(alfa)*cos(beta) + t.y*cos(alfa)*cos(beta) - t.z*sin(beta); tmp.z = t.x*sin(alfa)*sin(beta) + t.y*cos(alfa)*sin(beta) + t.z*cos(beta); return tmp;
}
/* Расчет вектора из вершины грани на лампочку */ XYZ VLamp( XYZ l, XYZ v) {
XYZ tmp;
tmp.x = l.x - v.x; tmp.y = l.y - v.y; tmp.z = l.z - v.z; return tmp;
}
/*Расчет длины вектора*/ double VLen( XYZ t) {
return sqrt(t.x*t.x + t.y*t.y + t.z*t.z);
}
/* Расчет координат нормального вектора к грани */
XYZ Normal(XYZ t1, XYZ t2, XYZ |
t3) { |
XYZ nn; |
- (t2.z-t1.z)*(t3.y-t1.y); |
nn.x = (t2.y-t1.y)*(t3.z-t1.z) |
|
nn.y = (t2.z-t1.z)*(t3.x-t1.x) |
- (t2.x-t1.x)*(t3.z-t1.z); |
nn.z = (t2.x-t1.x)*(t3.y-t1.y) |
- (t2.y-t1.y)*(t3.x-t1.x); |
return nn; |
|
} |
|
/* Расчет косинуса фи */ double CosFi( XYZ a, XYZ b) {
return (a.x*b.x + a.y*b.y + a.z*b.z)/(VLen(a)*VLen(b));
}
main() { /* Проверка */ unsigned char c;
int i, j;
XYZ s[20][20]; XYZ nnn; XYZ lll; XYZ Lamp; double cf;
/* Шаг 1 - расчет сетки для 3-мерного объекта */ for (i=0;i<20;i++) {
for (j=0;j<20;j++) { s[i][j].x=i*5+50; s[i][j].y=j*5+50; s[i][j].z=50*sin((i+j)/6.0)+50;
}
}
/* Шаг 2 - поворот граней сетки */ for (i=0;i<20;i++) {
for (j=0;j<20;j++) { s[i][j]=Rotate(s[i][j], 10, 25);
}
}
setvmode(0x13);
/* Отображение треугольников по точкам s[i,i] s[i+1,j] s[i,j+1] */ for (i=0;i<19;i++) {
for (j=0;j<19;j++) {
/* Рассчитали нормаль */ nnn=Normal(s[i][j], s[i+1][j], s[i][j+1]);
/* Рассчитать вектор на лампочку */ Lamp.x=30;
Lamp.y=180;
Lamp.z=210;
55
Климентьев К.Е. Компьютерная графика (курс лекций).
lll=VLamp( s[i][j], Lamp );
/* Рассчитать косинус фи между нормалью и вектором лампочки */ cf=CosFi(nnn,lll);
/* Нарисовать треугольник, закрасив его цветом, пропорциональным cos(фи) */ triang(
s[i][j].x, s[i][j].y, s[i+1][j].x, s[i+1][j].y, s[i][j+1].x, s[i][j+1].y, (cf+1)*8+16
); /* Нарисовать смежный треугольник для грани */
triang(
s[i+1][j+1].x, s[i+1][j+1].y, s[i+1][j].x, s[i+1][j].y, s[i][j+1].x, s[i][j+1].y, (cf+1)*8+16
);
}
} |
|
scanf("%c",&c); |
|
setvmode(3); |
|
} |
Вариант на Паскале |
|
|
uses dos; |
|
{-------------------------------------------------------------------------- |
} |
{Изменение графического режима}
procedure gmode(m:byte); var r:registers; begin r.ah:=0; r.al:=m; intr($10, r) end;
{Рисование точки с координатами x,y и цветом c}
procedure pix(x,y:integer; c:byte); begin mem[$A000:$140*y+x]:=c end;
{--------------------------------------------------------------------------}
{Обмен 2-х переменных своими значениями} procedure swap( var x, y : integer);
var tmp : integer; begin tmp:=x; x:=y; y:=tmp end;
{Расчет очередной точки прямой линии}
function countx(x1, y1, x2, y2, yy : integer) : integer; begin
if y2<>y1 then countx:=x1+((yy-y1)*(x2-x1)) div (y2-y1) else countx:=x1 end;
{Рисование закрашенного треугольника цветом c}
procedure triangol( xa, ya, xb, yb, xc, yc : integer; c : byte);
var x, y, x3, x4 : integer; |
|
|
begin |
|
swap(yc, yb) end; |
if (yc<yb) then begin swap(xc, xb); |
||
if (yc<ya) then begin swap(xc, xa); |
swap(yc, ya) end; |
|
if (yb<ya) then begin swap(xb, xa); |
swap(yb, ya) end; |
|
for y:=ya to yc do begin |
|
|
if (y<yb) then begin |
x4 := countx(xa, ya, xb, yb, y); |
|
x3 |
:= countx(xa, ya, xc, yc, y); |
|
if |
(x4<x3) then swap(x3, x4); for |
x:=x3 to x4 do pix(x,y,c); |
end |
|
|
else begin |
|
|
x3 |
:= countx(xa, ya, xc, yc, y); x4 := countx(xb, yb, xc, yc, y); |
|
if |
(x4<x3) then swap(x3, x4); for |
x:=x3 to x4 do pix(x,y,c); |
end end end; |
|
|
{-------------------------------------------------------------------------- |
|
} |
const |
pi=3.1415926; gr=pi/180.0; |
|
type xyz = record x, y, z : real end;
56
Климентьев К.Е. Компьютерная графика (курс лекций).
{Округление к ближайшему целому} function pin(x:real):integer; begin
if (x-round(x))<0.5 then pin:=round(x) else pin:=round(x+1.0); end;
{Поворот точки на углы alfa и beta для проецирования} procedure rot(var t: xyz; alfa, beta : real; var tmp:xyz); begin
alfa:=alfa*gr; beta:=beta*gr; tmp.x:=t.x*cos(alfa)-t.y*sin(alfa);
tmp.y:=t.x*sin(alfa)*cos(beta)+t.y*cos(alfa)*cos(beta)-t.z*sin(beta); tmp.z:=t.x*sin(alfa)*sin(beta)+t.y*cos(alfa)*sin(beta)+t.z*cos(beta);
end;
{Расчет длины вектора} function vlen(t:xyz):real;
begin vlen:=sqrt(sqr(t.x)+sqr(t.y)+sqr(t.z)) end;
{Определение координаты нормали к плоскости в точке } procedure normal(t1, t2, t3:xyz; var nn:xyz);
begin nn.x:=(t2.y-t1.y)*(t3.z-t1.z)-(t2.z-t1.z)*(t3.y-t1.y); nn.y:=(t2.z-t1.z)*(t3.x-t1.x)-(t2.x-t1.x)*(t3.z-t1.z); nn.z:=(t2.z-t1.z)*(t3.y-t1.y)-(t2.y-t1.y)*(t3.x-t1.x);
end;
{Расчет косинуса фи}
function cosfi(a, b:xyz):real;
begin cosfi:= (a.x*b.x+a.y*b.y+a.z*b.z)/(vlen(a)*vlen(b)) end; {----------------------------------------------------------------}
{Расчет точки для сферы}
procedure spoint(r, alfa, beta:real; var tmp:xyz); begin
alfa:=alfa*gr; beta:=beta*gr; tmp.x:=r*cos(alfa)*sin(beta); tmp.y:=r*cos(alfa)*cos(beta); tmp.z:=r*sin(alfa)
end;
{Расчет точки для тора}
procedure tpoint(r1, r2, alfa, beta:real; var tmp:xyz); begin
alfa:=alfa*gr; beta:=beta*gr; tmp.x:=(r1+r2*cos(alfa))*sin(beta); tmp.y:=(r1+r2*cos(alfa))*cos(beta); tmp.z:=r1*sin(alfa)
end;
{Расчет точки для цилиндра}
procedure cpoint(r, alfa, h, l:real; var tmp:xyz); begin
alfa:=alfa*gr;
tmp.x:=r*sin(alfa);
tmp.y:=r*cos(alfa);
tmp.z:=h*l;
end;
{Расчет точки поверхности, заданной красивым уравнением }
procedure |
apoint( |
xx, yy : real; var tmp:xyz ); |
begin |
xx*20.0+100; |
|
tmp.x := |
||
tmp.y := |
yy*20.0+100; |
|
tmp.z := |
(sin(xx)*sin(yy))*50.0; |
|
end; |
|
|
const mx=50; |
{Количество параллелей и меридианов} |
|
dx=6.28/mx; |
{Шаг сетки по X} |
|
dy=6.28/mx; |
{Шаг сетки по Y} |
57
Климентьев К.Е. Компьютерная графика (курс лекций).
var
i, j : integer; xx, yy : real;
setka |
: array |
[0..mx-1] of array [0..mx-1] of xyz; {Массив сетки} |
color |
: byte; |
{Цвет} |
norm |
: xyz; |
{координаты нормали} |
light |
: xyz; |
{координаты лампочки} |
cf |
: real; |
{косинус фи} |
begin
{Посчитать сетку узлов} yy:=-3.14;
for i:=0 to mx-1 do begin xx:=-3.14;
for j:=0 to mx-1 do begin apoint(xx, yy, setka[i][j]); xx:=xx+dx;
end;
yy:=yy+dy;
end;
{ Повернуть сетку на alfa=10 и beta=30 градусов } for i:=0 to mx-1 do begin
for j:=0 to mx-1 do begin
rot(setka[i][j], 10.0, 30.0, setka[i][j]) end
end;
{задаем координаты лампочки} light.x := 20;
light.y := 0; light.z := 20;
gmode($13); {Включение графического режима}
{Нарисовать сетку}
for i:=0 to mx-2 do begin for j:=0 to mx-2 do begin
{Расчитываем нормаль к грани, заданной 3-мя соседними вершинами} normal(setka[i][j], setka[i+1][j], setka[i][j+1], norm);
{Расчет косинуса фи между нормалью и вектором лампочки} cf := cosfi(norm, light);
{Расчет номера цвета - косинус от -1 до 1, результат будет от 16 до 31 } color := round((cf+1.0)*7.5)+16;
{Рисуем первый треугольник грани} triangol(
pin(setka[i][j].x), pin(setka[i][j].y), pin(setka[i+1][j].x), pin(setka[i+1][j].y), pin(setka[i][j+1].x), pin(setka[i][j+1].y), color);
{Рисуем второй треугольник грани} triangol(
pin(setka[i+1][j+1].x), pin(setka[i+1][j+1].y), pin(setka[i+1][j].x), pin(setka[i+1][j].y), pin(setka[i][j+1].x), pin(setka[i][j+1].y), color);
end end;
readln;
gmode(3); {Выключение графического режима}
end.
58