program Globe; uses Graph; const r = 50; {Радиус сферы} A = 0; {Коэффициенты общего уравнения плоскости} B = 0; C = 1; D = -50; sx = 300; {Координаты источника света} sy = 00; sz = -300; ex = 300; {Координаты наблюдателя} ey = 300; ez = 300; k_p = 0.5; {Коэффициенты поверхности} k_n = 0.5; k_m = 1; I_p = 64; I_n = 128; 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; {Углы} cos_alfa : real; cos_beta : real; cos_gama :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; 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; {Shadow} { 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; } {Sphere} 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); cos_alfa:= ((p.x)*(p.x-sx)+(p.y)*(p.y-sy)+(p.z)*(p.z-sz))/ (r*sqrt(sqr(p.x-sx)+sqr(p.y-sy)+sqr(p.z-sz))); cos_gama:= ((p.x)*(p.x-ex)+(p.y)*(p.y-ey)+(p.z)*(p.z-ez))/ (r*sqrt(sqr(p.x-ex)+sqr(p.y-ey)+sqr(p.z-ez))); {cos_beta:= cos_alfa*cos_gama+sqrt((1-sqr(cos_alfa))*(1-sqr(cos_gama)));} cos_beta:= cos(arctan(sqrt(1/sqr(cos_alfa) - 1)) + arctan(sqrt(1/sqr(cos_gama) - 1))); cos_alfa:= -cos_alfa; cos_beta:= -cos_beta; I:= trunc(K_p*I_P+K_n*I_n*cos_alfa+K_m*I_n*sqr(sqr(cos_beta))+32); if cos_alfa < 0 then i:= 100; if cos_beta > mCos then mCos:=cos_beta; 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.