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.