Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Метод построчной закраски треугольника ⇐ ПредыдущаяСтр 4 из 4
Наиболее просто осуществляется построчная закраска треугольника (в 3D графике треугольник – это основной элемент аппроксимации криволинейных поверхностей): 1. сортируем вершины треугольника по высоте: ‑ верхняя (X1,Y1) ‑ средняя (X3,Y3) ‑ нижняя (X2,Y2) 2. разбиваем на 2 треугольника: ‑ выше средней вершины (1,3,4) ‑ ниже средней вершины (4,3,2) => вводится новая псевдовершина (X4,Y4) 3. сортируем среднюю и новую вершины по горизонтали: ‑ левая (X4,Y4) ‑ правая (X3,Y3) 4. строим уравнения прямой для левого и правого ребер: ‑ от (X1,Y1) до (X4,Y4) - левая прямая (идентична (X1,Y1)-(X2,Y2)) ‑ от (X1,Y1) до (X3,Y3) - правая прямая-ребро по формуле X=(Y-Yn)*(Xk-Xn)/(Yk-Yn)+Xn 5. построчная закраска треугольника горизонтальными прямыми: внешний цикл for Y:=Y1 to Y3 внутренний цикл for X:=Xл(Y) to Xп(Y) 6. повторяем 4)-5) для нижнего треугольника for Y:=Y3 to Y2
X1,Y1
X4,Y4 X3,Y3
X2,Y2
Вместо одноцветного PutPixel (X, Y, C) можно использовать вывод точек, например, из картинки 32х32 пикселя: PutPixel (X, Y, sprite [ X mod 32, Y mod 32]). 5. Контрольные вопросы
1. Геометрические основы машинной графики. Основные понятия. 2. Представление объекта в виде каркаса. 3. Перенос и масштабирование объектов. 4. Поворот объекта вокруг осей координат. 5. Алгоритмы удаления скрытых линий и поверхностей. 6. Алгоритм художника. Неопределенности. Тесты. 7. Алгоритм с использованием Z-буфера. 8. Алгоритм трассировки лучей. 8. Модели освещения. Диффузное отражение. 9. Модели освещения. Зеркальное отражение. 10. Модели освещения. Общая формула интенсивности и значение 11. Закраска объекта, аппроксимированного полигональной сеткой. 12. Закраска объекта, аппроксимированного полигональной сеткой.
13. Закраска объекта, аппроксимированного полигональной сеткой. 6. Выбор варианта задания для студентов Лаб. раб. № 2 «3D-изображения: Лаб. раб. № 3 «3D-изображения: удаление невидимых граней» закраска видимых граней» Лаб. Раб. № 2 «Движение каркасных объектов с простой закраской» Лаб. Раб. № 3 «Движение закрашенного объекта с учетом освещения»
Модели объекта (-ов), их цвет и движение у всех должны отличаться.
Содержание общего отчета
1. Геометрическая модель сцены с указанием точки наблюдения и источников освещения. 2. Описание используемого алгоритма удаления невидимых поверхностей. 3. Описание используемого алгоритма закраски. 4. Исходный текст программы с комментариями. 5. Результат работы (скрин-шот). 6. Выводы с личными впечатлениями от работы. Пример программы на языке Delphi
Фон примера лаб.раб №2 черный, объект – четырехугольная звезда (шестеренка). В нормальном режиме (когда не выбран метод удаления невидимых ребер и граней) рисуется каркасный объект с ребрами разного цвета, в режиме «удаления» (которые необходимо реализовать самостоятельно) грани должны закрашиваться разным цветом. В режиме просмотра («демо») грани отображаются без сортировки (в порядке их описания). Возникающие артефакты удаления необходимо описать в выводах. Градиентную закраску Гуро или Фонга для лаб.раб №3 от направления освещения сделать самостоятельно на базе алгоритма построчной развертки треугольников согласно индивидуального задания (второй пример). Вектор освещения можно задать ткнувшись в изображение.
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
type TForm1 = class(TForm) Image1: TImage; CheckBox1: TCheckBox; Timer1: TTimer; Panel1: TPanel; RadioButton1: TRadioButton; RadioButton3: TRadioButton; RadioButton4: TRadioButton; RadioButton5: TRadioButton; RadioButton2: TRadioButton; Panel2: TPanel; RadioButton6: TRadioButton; RadioButton7: TRadioButton; RadioButton8: TRadioButton; RadioButton9: TRadioButton; procedure CheckBox1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.CheckBox1Click(Sender: TObject); begin Timer1.Enabled:=CheckBox1.Checked; end;
const k_v=24; { количество вершин } k_r=44; { количество ребер } k_g=22; { количество граней } d=-1000; { центр. проекция }
type m_v=array[1..k_v,1..3] of single; //массив вершин - XYZ m_r=array[1..k_r,1..2] of integer; //массив ребер - ном.вершин m_v2=array[1..k_v,1..3] of integer; m_g=array[1..k_g,1..5] of integer; //массив граней (до5ном.вершин)
var a:m_v; { массив вершин } b:m_r; { массив ребер } g:m_g; { массив граней } p,a1,a2:m_v; pr:m_v2; { массив вершин в проекции } q,w,e,kx,ky,kz,wx,wy,wz,rad:integer; x0,y0,z0,x,y,ugol,z1:single; f:boolean; xv1,yv1,xv2,yv2:integer; maxX, maxY:integer; VAR oX,oY,oZ:single; // вектор освещения
{----- Масштабирование -----} procedure MASH(var a,b:m_v; kx,ky,kz:integer); var q:integer; begin for q:=1 to k_v do begin b[q,1]:=a[q,1]*kx; b[q,2]:=a[q,2]*ky; b[q,3]:=a[q,3]*kz; end; end;
{----- Поворот фигуры -----} procedure POVOROT(var a,b:m_v; wx,wy,wz:integer); var q:integer; ug,co,si:single; c,c1:m_v; begin c:=a; c1:=c; if wx<>0 then begin ug:=wx*pi/180; for q:=1 to k_v do begin co:=cos(ug); si:=sin(ug); c[q,2]:=c1[q,2]*co-c1[q,3]*si; c[q,3]:=c1[q,2]*si+c1[q,3]*co; c[q,1]:=c1[q,1]; end; c1:=c; end; if wy<>0 then begin ug:=wy*pi/180; for q:=1 to k_v do begin co:=cos(ug); si:=sin(ug); c[q,1]:=c1[q,1]*co+c1[q,3]*si; c[q,3]:=-c1[q,1]*si+c1[q,3]*co; c[q,2]:=c1[q,2]; end; c1:=c; end; if wz<>0 then begin ug:=wz*pi/(180*0.5); for q:=1 to k_v do begin co:=cos(ug); si:=sin(ug); c[q,1]:=c1[q,1]*co-c1[q,2]*si; c[q,2]:=c1[q,1]*si+c1[q,2]*co; c[q,3]:=c1[q,3]; end; c1:=c; end; b:=c1; end;
{----- Перенос -----} procedure PERENOS(var a,b:m_v; var dx,dy,dz:single); var q:integer; begin for q:=1 to k_v do begin b[q,1]:=a[q,1]+dx; b[q,2]:=a[q,2]+dy; b[q,3]:=a[q,3]+dz; end; end;
{----- Проекция на плоскость экрана -----} procedure PROEK(var a:m_v; var b:m_v2); var q:integer; z,xx,yy:single; begin xx:=maxX/2; yy:=maxY/2; for q:=1 to k_v do begin z:=a[q,3]; b[q,1]:=round(a[q,1]*d/z+xx); b[q,2]:=round(a[q,2]*d/z+yy); b[q,3]:=round(a[q,3]*100); end; end;
procedure TForm1.FormCreate(Sender: TObject); begin {------ Задание вершин шестеренки с 4 зубцами ------} a[1,1]:=0.25;a[1,2]:=0;a[1,3]:=0; a[2,1]:=0.75;a[2,2]:=0;a[2,3]:=0; a[3,1]:=1;a[3,2]:=1;a[3,3]:=0; a[4,1]:=0;a[4,2]:=1;a[4,3]:=0; a[5,1]:=0.25;a[5,2]:=0;a[5,3]:=0.5; a[6,1]:=0.75;a[6,2]:=0;a[6,3]:=0.5; a[7,1]:=1;a[7,2]:=1;a[7,3]:=0.5; a[8,1]:=0;a[8,2]:=1;a[8,3]:=0.5; a[9,1]:=-1;a[9,2]:=1.25;a[9,3]:=0; a[10,1]:=-1;a[10,2]:=1.75;a[10,3]:=0; a[11,1]:=0;a[11,2]:=2;a[11,3]:=0; a[12,1]:=-1;a[12,2]:=1.25;a[12,3]:=0.5; a[13,1]:=-1;a[13,2]:=1.75;a[13,3]:=0.5; a[14,1]:=0;a[14,2]:=2;a[14,3]:=0.5; a[15,1]:=0.25;a[15,2]:=3;a[15,3]:=0; a[16,1]:=0.75;a[16,2]:=3;a[16,3]:=0; a[17,1]:=1;a[17,2]:=2;a[17,3]:=0; a[18,1]:=0.25;a[18,2]:=3;a[18,3]:=0.5; a[19,1]:=0.75;a[19,2]:=3;a[19,3]:=0.5; a[20,1]:=1;a[20,2]:=2;a[20,3]:=0.5; a[21,1]:=2;a[21,2]:=1.75;a[21,3]:=0; a[22,1]:=2;a[22,2]:=1.25;a[22,3]:=0; a[23,1]:=2;a[23,2]:=1.75;a[23,3]:=0.5; a[24,1]:=2;a[24,2]:=1.25;a[24,3]:=0.5; {-------- Задание граней -------------} g[1,1]:=1;g[1,2]:=2;g[1,3]:=3;g[1,4]:=4; g[2,1]:=5;g[2,2]:=8;g[2,3]:=7;g[2,4]:=6; g[3,1]:=1;g[3,2]:=5;g[3,3]:=6;g[3,4]:=2; g[4,1]:=3;g[4,2]:=2;g[4,3]:=6;g[4,4]:=7; g[5,1]:=1;g[5,2]:=4;g[5,3]:=8;g[5,4]:=5; g[6,1]:=7;g[6,2]:=8;g[6,3]:=14;g[6,4]:=20; g[7,1]:=4;g[7,2]:=9;g[7,3]:=12;g[7,4]:=8; g[8,1]:=8;g[8,2]:=12;g[8,3]:=13;g[8,4]:=14; g[9,1]:=9;g[9,2]:=10;g[9,3]:=13;g[9,4]:=12; g[10,1]:=10;g[10,2]:=11;g[10,3]:=14;g[10,4]:=13; g[11,1]:=9;g[11,2]:=4;g[11,3]:=11;g[11,4]:=10; g[12,1]:=3;g[12,2]:=17;g[12,3]:=11;g[12,4]:=4; g[13,1]:=11;g[13,2]:=15;g[13,3]:=18;g[13,4]:=14; g[14,1]:=15;g[14,2]:=16;g[14,3]:=19;g[14,4]:=18; g[15,1]:=16;g[15,2]:=17;g[15,3]:=20;g[15,4]:=19; g[16,1]:=14;g[16,2]:=18;g[16,3]:=19;g[16,4]:=20; g[17,1]:=11;g[17,2]:=17;g[17,3]:=16;g[17,4]:=15; g[18,1]:=17;g[18,2]:=21;g[18,3]:=23;g[18,4]:=20; g[19,1]:=21;g[19,2]:=22;g[19,3]:=24;g[19,4]:=23; g[20,1]:=22;g[20,2]:=3;g[20,3]:=7;g[20,4]:=24; g[21,1]:=20;g[21,2]:=23;g[21,3]:=24;g[21,4]:=7; g[22,1]:=3;g[22,2]:=22;g[22,3]:=21;g[22,4]:=17; {-------- Задание ребер -------------}
b[1,1]:=1;b[1,2]:=2; b[2,1]:=2;b[2,2]:=3; b[3,1]:=3;b[3,2]:=4; b[4,1]:=4;b[4,2]:=1; b[5,1]:=5;b[5,2]:=6; b[6,1]:=6;b[6,2]:=7; b[7,1]:=7;b[7,2]:=8; b[8,1]:=8;b[8,2]:=5; b[9,1]:=1;b[9,2]:=5; b[10,1]:=2;b[10,2]:=6; b[11,1]:=3;b[11,2]:=7; b[12,1]:=4;b[12,2]:=8; b[13,1]:=4;b[13,2]:=9; b[14,1]:=9;b[14,2]:=10; b[15,1]:=10;b[15,2]:=11; b[16,1]:=4;b[16,2]:=11; b[17,1]:=8;b[17,2]:=12; b[18,1]:=12;b[18,2]:=13; b[19,1]:=13;b[19,2]:=14; b[20,1]:=14;b[20,2]:=8; b[21,1]:=9;b[21,2]:=12; b[22,1]:=10;b[22,2]:=13; b[23,1]:=11;b[23,2]:=14; b[24,1]:=11;b[24,2]:=15; b[25,1]:=15;b[25,2]:=16; b[26,1]:=16;b[26,2]:=17; b[27,1]:=17;b[27,2]:=11; b[28,1]:=14;b[28,2]:=18; b[29,1]:=18;b[29,2]:=19; b[30,1]:=19;b[30,2]:=20; b[31,1]:=20;b[31,2]:=14; b[32,1]:=15;b[32,2]:=18; b[33,1]:=16;b[33,2]:=19; b[34,1]:=17;b[34,2]:=20; b[35,1]:=17;b[35,2]:=21; b[36,1]:=21;b[36,2]:=22; b[37,1]:=22;b[37,2]:=3; b[38,1]:=3;b[38,2]:=17; b[39,1]:=20;b[39,2]:=23; b[40,1]:=23;b[40,2]:=24; b[41,1]:=24;b[41,2]:=7; b[42,1]:=23;b[42,2]:=21; b[43,1]:=22;b[43,2]:=24; b[44,1]:=7;b[44,2]:=20; {-----------------------} x0:=0; y0:=0; z0:=0; { начальные координаты } kx:=2; ky:=2; kz:=2; { коэффициенты масштабирования } wx:=1; wy:=1; wz:=0; { углы поворота шестеренки } MASH(a,a1, kx,ky,kz); ugol:=0; rad:=10; z1:=10; { движения шестеренки } oX:=1; oY:=1; oZ:=1; //нормированный вектор maxX:=Image1.Width; maxY:=Image1.Height; end; //============== процедура для 3 лаб.работы - закраска граней ================== procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); //задаем вектор освещения из мыши в центр var xx,yy,zz:integer; rr:single; begin xx:=X-maxX div 2; yy:=Y-maxY div 2; zz:=400-Round(sqrt(sqr(xx)+sqr(yy))); rr:=sqrt(sqr(xx)+sqr(yy)+sqr(zz)); oX:=xx/rr; oY:=yy/rr; oZ:=zz/rr; end; //замена Poligon(), но с другими параметрами procedure Polygon123(var aa:m_v2; gr:integer); //аa-массив спроецированных вершин 2D var q,i:integer; ver:array[1..4,1..3] of single; //массив нормалей 4 вершин грани gr begin //gr-номер грани из g[gr] With Form1,Form1.Image1.Canvas do begin if RadioButton6.Checked then begin //Гуро - например //на входе грань g[gr] с 4 вершинами - ищем соседние грани в g[] для каждой вершины //далее 4 раза:для соседних граней с вершинами из a2[] находим нормали и усредняем // по вектору освещения (oX,oY,oZ) и этой нормали определяем интенсивность в вершине // далее 2 раза: закрашиваем треугольники 123 и 341 из вершин грани с интерполяцией end; end; end;
{================= Рисование фигуры для 2 лабы ============================} procedure PRINT0(var a:m_v2; var b:m_r); //а-массив вершин, уже спроецированный, т.е.2D var q,i,v1,v2, x1,x2,y1,y2:integer; sort:boolean; //b-массив ребер, не изменяется poly:array[1..4] of Tpoint; // грань remas:array[1..k_g] of integer; //массив косвенной сортировки по Z begin xv1:=maxX-1; yv1:=maxY-1; xv2:=0; yv2:=0; // габариты грани for i:=1 to k_g do remas[i]:=i; {del unview} With Form1,Form1.Image1.Canvas do begin Brush.Color:=clWhite; Pen.Color:=clWhite; //доступ к графике if RadioButton5.Checked then for q:=1 to k_g do begin //demo Poly[1].X:=a[g[q,1],1]; Poly[1].Y:=a[g[q,1],2]; Poly[2].X:=a[g[q,2],1]; Poly[2].Y:=a[g[q,2],2]; Poly[3].X:=a[g[q,3],1]; Poly[3].Y:=a[g[q,3],2]; Poly[4].X:=a[g[q,4],1]; Poly[4].Y:=a[g[q,4],2]; Brush.Color:=Brush.Color-080808; Polygon(Poly); end; if RadioButton1.Checked then begin {sort of Zmax - Художника}
Repeat sort:=false; //сортировка граней, рекомендуется в отдельном массиве
Until not sort; {sort of Zmax}(**) // рисуем грани for q:=1 to k_g do begin for i:=1 to 4 do begin poly[i].X:=000; poly[i].Y:=111; end; Brush.Color:=clGray; if false then Polygon(Poly); end; end; // можно свои цвета и разные if RadioButton2.Checked then begin Brush.Color:=clGreen; //ориентация граней по формуле for q:=1 to k_g do begin //poly[].X:=
Brush.Color:=clGreen; if false then Polygon(Poly); end; end; {only karkas} if RadioButton3.Checked then begin end; //трассировка лучей if RadioButton4.Checked then begin end; //Z-буфер if RadioButton9.Checked then for q:=1 to k_r do begin v1:=b[q,1]; v2:=b[q,2]; //рисуем ребра x1:=a[v1,1]; y1:=a[v1,2]; x2:=a[v2,1]; y2:=a[v2,2]; if x1<xv1 then xv1:=x1 else if x1>xv2 then xv2:=x1; // габариты if x2<xv1 then xv1:=x2 else if x2>xv2 then xv2:=x2; if y1<yv1 then yv1:=y1 else if y1>yv2 then yv2:=y1; if y2<yv1 then yv1:=y2 else if y2>yv2 then yv2:=y2; Pen.Color:=Pen.Color-080808; MoveTo(x1,y1); LineTo(x2,y2); end; if xv1<0 then xv1:=0; if xv2<0 then xv2:=0; if yv1<0 then yv1:=0; if yv2<0 then yv2:=0; end; end;
procedure TForm1.Timer1Timer(Sender: TObject); var i,j:integer; cc:tcolor; begin //рисование Image1.Canvas.Brush.Color:=clBlack; Image1.Canvas.FillRect(Rect(0,0,Image1.Width,Image1.Height)); //640x480 POVOROT(a1,a2, wx,wy,wz); a1:=a2; //вариант относительных поворотов //wx:=wx+1; wy:=wy+1; //wz:=wz+1; //вариант абсолютных поворотов x:=rad*sin(ugol); y:=rad*cos(ugol); ugol:=ugol+pi/180; if (z1<140)and(not(f)) then z1:=z1+1 else f:=true; if (z1>=40)and(f) then z1:=z1-1 else f:=false; PERENOS(a2,p, x,y,z1); PROEK(p,pr); // While (port[$3DA] and 8)<>0 do; { wait end sync } // While (port[$3DA] and 8)=0 do; { wait begin sync } PRINT0(pr, b); {paint} end;
end. { unit1.dfm } object Form1: TForm1 Left = 192 Top = 118 Width = 847 Height = 541 Caption = #1040#1085#1080#1084#1072#1090#1086#1088'3D' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object Image1: TImage Left = 8 Top = 8 Width = 641 Height = 481 OnMouseDown = Image1MouseDown end object CheckBox1: TCheckBox Left = 680 Top = 48 Width = 97 Height = 33 Caption = #1076#1074#1080#1078#1077#1085#1080#1077 TabOrder = 0 OnClick = CheckBox1Click end object Panel1: TPanel Left = 664 Top = 120 Width = 153 Height = 161 Caption = #1052#1077#1090#1086#1076#1099' '#1091#1076#1072#1083#1077#1085#1080#1103':' Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False TabOrder = 1 object RadioButton1: TRadioButton Left = 16 Top = 24 Width = 113 Height = 17 Caption = #1061#1091#1076#1086#1078#1085#1080#1082#1072 TabOrder = 0 end object RadioButton3: TRadioButton Left = 16 Top = 96 Width = 121 Height = 17 Caption = #1090#1088#1072#1089#1089#1080#1088#1086#1074#1082#1072' '#1083#1091#1095#1077#1081 TabOrder = 1 end object RadioButton4: TRadioButton Left = 16 Top = 112 Width = 113 Height = 17 Caption = 'Z-'#1073#1091#1092#1077#1088 TabOrder = 2 end object RadioButton5: TRadioButton Left = 16 Top = 0 Width = 113 Height = 17 Caption = '-demo-' TabOrder = 3 end object RadioButton2: TRadioButton Left = 16 Top = 40 Width = 121 Height = 17 Caption = #1086#1088#1080#1077#1085#1090#1072#1094#1080#1103' '#1075#1088#1072#1085#1077#1081 TabOrder = 4 end object RadioButton9: TRadioButton Left = 16 Top = 136 Width = 113 Height = 17 Caption = #1090#1086#1083#1100#1082#1086' '#1082#1072#1088#1082#1072#1089 Checked = True TabOrder = 5 TabStop = True end end object Panel2: TPanel Left = 664 Top = 320 Width = 153 Height = 169 Caption = #1052#1077#1090#1086#1076#1099' '#1079#1072#1082#1088#1072#1089#1082#1080':' TabOrder = 2 object RadioButton6: TRadioButton Left = 32 Top = 24 Width = 89 Height = 17 Caption = #1052#1077#1090#1086#1076' '#1043#1091#1088#1086 TabOrder = 0 end object RadioButton7: TRadioButton Left = 32 Top = 48 Width = 105 Height = 17 Caption = #1052#1077#1090#1086#1076' '#1060#1086#1085#1075#1072 TabOrder = 1 end object RadioButton8: TRadioButton Left = 32 Top = 112 Width = 97 Height = 17 Caption = #1060#1086#1090#1086#1075#1088#1072#1092#1080#1103 TabOrder = 2 end end object Timer1: TTimer Enabled = False Interval = 100 OnTimer = Timer1Timer Left = 792 Top = 48 end end Выводы: 1. Самостоятельная программная реализация алгоритма движения трехмерного каркасного объекта и удаления его невидимых граней позволяет освоить преобразование координат и законы проекции.
2. Самостоятельная программная реализация алгоритма закраски видимых граней с учетом источника освещения позволяет изучить законы освещения и повысить реалистичность изображения.
Учебное издание
Составитель Егоров Станислав Феликсович
|
|||||||||||||||||
Последнее изменение этой страницы: 2020-10-24; просмотров: 205; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.17.128.129 (0.166 с.) |