program Globe; uses Graph; const r = 50; {Радиус сферы} A = 0; {Коэффициенты общего уравнения плоскости} B = 0; C = 1; D = -50; sx = 100; {Координаты источника света} sy = 100; sz = 00; ex = 00; {Координаты наблюдателя} ey = 00; ez = 100; kp = 1; {Коэффициенты поверхности} kn = 1; km = 1; Ip = 100; Ina = 42; step = 0.01; {Шаг изменения угла(один градус)} type tPoint = record {Точка} x, y, z: real end; tLine = record {Отрезок} bol, eol: tPoint end; tPlane = record {Плоскость} A, B, C, D: real end; tVector = record {Вектор} x, y, z: real end; var Gd, Gm : integer; {Графика} p : tPoint; {Точки} pInt : tPoint; {Точка пересечения} plane : tPlane; {Поверхность} spot : tPoint; {Источник света} lin : tLine; {Прямая} I : byte; {Яркость поверхности} alfa, beta: real; {Углы} cosA : real; cosB : real; mCos:real; procedure SetPalette; var i : integer; R, G, B : integer; begin for i:=16 to 255 do begin if i<32 then begin R:=0; G:=0; B:=0; end else if i<96 then begin R:=i-32; G:=0; B:=0; end else if i<128 then begin R:=255; G:=2*i-192; B:=0; end else begin R:=511-2*i; G:=255; B:=2*i-256; end; SetRGBPalette(i,R,G,B); end; end; { procedure SetPalette; const stepC = 1; var i: integer; cR: integer; cO: integer; begin for i:= 100 to 156 do begin SetRGBPalette(i, cR, 0, 0); cR:= cR + stepC; end; cO:= 7; for i:= 157 to 163 do begin SetRGBPalette(i, cR, cO, cO); cO:= cO - stepC; end; end; } procedure Proection(var p: tPoint); {Изометрическая проекция} var oldX:real; begin oldX:=p.x; p.x:= GetMaxX div 2 + (sqrt(3)*(p.y - p.x))/2; p.y:= GetMaxY div 2 + p.z + (p.y + oldX)/2; end; procedure Interception(l: tLine; s: tPlane); {Исследование взаимного} var { положения } p: tVector; { прямой и плоскости } M, N, t: real; begin p.x:= l.bol.x - l.eol.x; p.y:= l.bol.y - l.eol.y; p.z:= l.bol.z - l.eol.z; M:= s.A*p.x + s.B*p.y + s.C*p.z; N:= s.A*l.bol.x + s.B*l.bol.y + s.C*l.bol.z + s.D; if M <> 0 then begin t:= -(N)/M; pInt.x:= l.bol.x + p.x*t; pInt.y:= l.bol.y + p.y*t; pInt.z:= (l.bol.z + p.z*t); end; end; function CosAlfa(p: tPoint): real; {Косинус угла между векторами} var c, z: real; b: tVector; begin b.x:= (p.x - sx); b.y:= (p.y - sy); b.z:= (p.z - sz); c:= -p.x*b.x - p.y*b.y - p.z*b.z; z:= sqrt(sqr(b.x) + sqr(b.y) + sqr(b.z))*r; CosAlfa:= c/z; end; function CosBeta(cosA: real; p: tPoint): real; {Косинус угла между векторами} var c, z: real; v: tVector; cos_n_e: real; begin v.x:= (ex - p.x); v.y:= (ey - p.y); v.z:= (ez - p.z); c:= - p.x*v.x - p.y*v.y - p.z*v.z; z:= sqrt(sqr(v.x) + sqr(v.y) + sqr(v.z))*r; cos_n_e:= c/z; CosBeta:= cos_n_e*cosA - sqrt(1 - sqr(cos_n_e))*sqrt(1 - sqr(cosA)); end; begin {Инициализация графики} Gd:= InstallUserDriver('svga256', nil); Gm:= 2; InitGraph(Gd, Gm, 'd:\'); SetPalette; {Рисование} SetFillStyle(SolidFill, 7); FillEllipse(500, 400, 1000, 1000); plane.A:= A; plane.B:= B; plane.C:= C; plane.D:= D; spot.x:= sx; spot.y:= sy; spot.z:= sz; lin.bol:= spot; alfa:= 0; while alfa <= pi do begin beta:= 0; while beta < 2*pi do begin p.x:= r*Sin(alfa)*Cos(beta); p.y:= r*Sin(alfa)*Sin(beta); p.z:= r*Cos(alfa); lin.eol:= p; Interception(lin, plane); Proection(pInt); PutPixel(Round(pInt.x), Round(pInt.y), 133); {Тень тени} beta:= beta + step; end; alfa:= alfa + step; end; spot.x:= sx; spot.y:= sy; spot.z:= sz; alfa:= 0; while alfa <= pi do begin beta:= 0; while beta < 2*pi do begin p.x:= r*Sin(alfa)*Cos(beta); p.y:= r*Sin(alfa)*Sin(beta); p.z:= r*Cos(alfa); cosA:= CosAlfa(p); { if (cosB<=0)and(cosB >=-0.1) then I:= white else } I:= Round(kp*Ip + kn*Ina*cosA {+ km*Ina*sqr(sqr(cosB))}); if cosA < 0 then i:= 100; cosB:= CosBeta(cosA, p); if cosB > mCos then mCos:= cosB; Proection(p); PutPixel(Trunc(p.x), Trunc(p.y), I); {Точки сферы} beta:= beta + step; end; alfa:= alfa + step; end; Proection(spot); SetFillStyle(SolidFill, yellow); FillEllipse(round(spot.x), round(spot.y), 3, 3); ReadLn; CloseGraph; end.