unit _Planet;

interface

Uses
  OpenGL,
  _Geometry,
  _Noise,
  _2d,
  _sysutils,
  _world,
  _forms;

const
  //planet
  pl_size = 15;
  pl_p = 16;
  pl_scale = 0.5;
  tex_size = 1024;


type
  TTex = array [0..tex_size*tex_size*4] of byte;
  TCube_map = Array [0..5] of cardinal;
  Trgb = array [0..3] of byte;

  TPlanet = class
    private
     Rad:Single;
     tip,c_tip:byte;
     Vp:Array [0..((pl_p+1)*(pl_p+1))*3] of Single;
     Tp:Array [0..((pl_p+1)*(pl_p+1))*2] of Single;
     Np:Array [0..((pl_p+1)*(pl_p+1))*3] of Single;
     Fp:Array [0..((pl_size+1)*(pl_size+1))*4] of cardinal;
     num_faces:cardinal;
     pTex,cTex,aTex,sTex:TCube_map;
     ang,ang_s:single;
     Atmosphere_color:TPoint;
     function Get_H(t:byte;p:TPoint):single;
     function Get_C(t:byte;p:TPoint):single;
     function Get_CLR(tip:byte;n,val:Single):Trgb;
     procedure Draw_Planet(var pTex:TCube_map);
     procedure Generate_Planetar_Texture(a,b,c:TPoint;var tex,tex_c,tex_a:Cardinal);
     procedure Generate_Sky_Texture(a,b,c:TPoint;var Tex_s:Cardinal);
     procedure Create_Geometry;
    public
     WL:single;//scale
     AX,AY,AL:single;//rotate,scale
     Show_Atmosphere,Show_Clouds:boolean;
     pts:array [0..25] of TPoint;
     ptip:array [0..25] of byte;
     seed:byte;
     constructor Create(tip,rad:byte);
     procedure Render;
  end;

var planet:TPlanet;


implementation

{$REGION 'Noise_Function'}
function TPlanet.Get_H(t:byte;p:TPoint):single;
Var
 A:Single;
begin   
 A:=0; 
 case t of
  0:begin
    A:=(Get_PN(p[0]+seed,p[1],p[2],1102)-128)/2+
       (Get_PN(p[0],p[1]+seed,p[2],551)-128)/4+
       (Get_PN(p[0],p[1],p[2]+seed,265)-128)/8+
       (Get_PN(p[0]+seed,p[1],p[2],129)-128)/16+128;
  end;
  1:begin
    A:=(Get_PN(p[0],p[1]+seed,p[2],502)-128)/2+
       (Get_PN(p[0],p[1],p[2]+seed,251)-128)/4+
       (Get_PN(p[0],p[1],p[2]+seed,125)-128)/8+
       (Get_PN(p[0]+seed,p[1],p[2],79)-128)/16+128;
  end;
  2:begin
    A:=(Get_PN(p[0],p[1]+seed,p[2],129)-128)/2+
       (Get_PN(p[0]+seed,p[1],p[2],65)-128)/4+
       (Get_PN(p[0],p[1]+seed,p[2],35)-128)/8+128;
    A:=A*0.1+(p[2]+rad)/rad*0.5*255;
  end;
 end;
 Get_H:=A;
end;

function TPlanet.Get_C(t:byte;p:TPoint):single;
Var
 A,B,C,d:Single;
begin
 A:=0; 
 case t of
  0:begin
    A:=(Get_PN(p[0]+seed,p[1],p[2],128)-128)/4+
       (Get_PN(p[0],p[1]+seed,p[2],64)-128)/8+
       (Get_PN(p[0],p[1],p[2]+seed,32)-128)/16;
    A:=A+128+60;//64;
  end;
  1:begin
    A:=(Get_PN(p[0]+seed,p[1],p[2],128)-128)/4+
       (Get_PN(p[0],p[1]+seed,p[2],64)-128)/8+
       (Get_PN(p[0],p[1],p[2]+seed,32)-128)/16;
    A:=A+128+60;//64;
  end;
  2:begin
    A:=(Get_PN(p[0]+seed,p[1],p[2]*4,256)-128)/4+
       (Get_PN(p[0],p[1]+seed,p[2]*4,128)-128)/8+
       (Get_PN(p[0],p[1],(p[2]+seed)*4,64)-128)/16;
    A:=A+128+60;//64;
  end;
 end;
 Get_C:=A;
end;

function TPlanet.Get_CLR(tip:byte;n,val:Single):Trgb;
var
 f,t:single;
 clr,c1,c2,c3:TRGB;
begin
 clr[0]:=20;
 clr[1]:=120;
 clr[2]:=20;
 if val>255 then val:=255;
 if val<0 then val:=0;

 case tip of
  0:begin //usual
    if val<123 then clr[2]:=200;
    if (val>=123) and (val<128) then clr[2]:=200-trunc((val-123)*36);
   { if (val>=123) and (val<128) then
     begin
      clr[0]:=255-trunc((val-123)*28);
      clr[1]:=255-trunc((val-123)*28);
      clr[2]:=20+trunc((val-123)*20);
     end else           }
    clr[1]:=Round(val);
  end;
  1:begin //usual
    clr[0]:=40;
    clr[1]:=40;
    clr[2]:=40;
    clr[0]:=Round(val);
    if (val>=173) and (val<183) then clr[1]:=trunc(val*0.8*(val-173)*0.1+40*(1-(val-173)*0.1));
    if (val>=183) then clr[1]:=trunc(val*0.8);
  end;
  2:begin //neptune
    clr[0]:=40;
    clr[1]:=40;
    clr[2]:=40;
    f:=trunc(val/12);
    t:=(val-f*12)/(255/12);
    c1[0]:=trunc(Get_Y_V(Get_R(seed+70),Get_X_V(Get_R(seed*5),250)));
    c1[1]:=trunc(Get_X_V(Get_R(seed+70),250));
    c1[2]:=trunc(Get_Y_V(Get_R(seed+70),Get_Y_V(Get_R(seed*5),250)));
    c2[0]:=trunc(Get_Y_V(Get_R(seed+130),Get_X_V(Get_R(seed*5+80),250)));
    c2[1]:=trunc(Get_X_V(Get_R(seed+130),250));
    c2[2]:=trunc(Get_Y_V(Get_R(seed+130),Get_Y_V(Get_R(seed*5+80),250)));
    c3[0]:=trunc(Get_Y_V(Get_R(seed+190),Get_X_V(Get_R(seed*5+140),250)));
    c3[1]:=trunc(Get_X_V(Get_R(seed+190),250));
    c3[2]:=trunc(Get_Y_V(Get_R(seed+190),Get_Y_V(Get_R(seed*5+140),250)));
    case trunc(f) mod 3 of
     0:begin
       clr[0]:=trunc(c1[0]*(1-t)+c2[0]*(t));
       clr[1]:=trunc(c1[1]*(1-t)+c2[1]*(t));
       clr[2]:=trunc(c1[2]*(1-t)+c2[2]*(t));
     end;
     1:begin
       clr[0]:=trunc(c2[0]*(1-t)+c3[0]*(t));
       clr[1]:=trunc(c2[1]*(1-t)+c3[1]*(t));
       clr[2]:=trunc(c2[2]*(1-t)+c3[2]*(t));
     end;
     2:begin
       clr[0]:=trunc(c3[0]*(1-t)+c1[0]*(t));
       clr[1]:=trunc(c3[1]*(1-t)+c1[1]*(t));
       clr[2]:=trunc(c3[2]*(1-t)+c1[2]*(t));
     end;
    end;
    {clr[0]:=Round(val);
    if (val>=173) and (val<183) then clr[1]:=trunc(val*0.8*(val-173)*0.1+40*(1-(val-173)*0.1));
    if (val>=183) then clr[1]:=trunc(val*0.8);  }
  end;
  10:begin //Clouds
    F:=val;
    if f<(128+64) then t:=0 else
    if f>(128+84) then t:=1 else
     t:=(f-128-64)/20;
    if f>255 then f:=255;
    clr[3]:=round(t*255);
    clr[0]:=Round(f);
    clr[1]:=Round(f);
    clr[2]:=Round(f);
  end;
  11:begin //Clouds
    f:=val-trunc(val/8)*8;
    t:=((abs(f-4)*32)*4-255)/255*(n-128)*4;//abs((f-32)*8)-128;
    if t<0 then t:=0;
    if t>255 then t:=255;
    f:=n;
    clr[0]:=Round(f);
    clr[1]:=Round(f);
    clr[1]:=clr[0];
    clr[2]:=clr[0];
  end;
  12:begin //Clouds  
    c1[0]:=trunc(Get_Y_V(Get_R(seed+70),Get_X_V(Get_R(seed*5),250)));
    c1[1]:=trunc(Get_X_V(Get_R(seed+70),250));
    c1[2]:=trunc(Get_Y_V(Get_R(seed+70),Get_Y_V(Get_R(seed*5),250)));
    Atmosphere_color:=Point(c1[0]/250,c1[1]/250,c1[2]/250);
    F:=val;
    if f<(128+64) then t:=0 else
    if f>(128+84) then t:=1 else
     t:=(f-128-64)/20;
    if f>255 then f:=255;
    if f<0 then f:=0;
    clr[0]:=Round(f*c1[0]/255);
    clr[1]:=Round(f*c1[1]/255);
    clr[2]:=Round(f*c1[2]/255);   
    clr[3]:=round(t*255);
  end;
 end;
 Get_CLR:=clr;
end;
{$ENDREGION}

{$REGION 'create texture'}
function GenTexture(Var pData: Pointer;Width: LongWord;Height: LongWord; var Texture: GLuint): Boolean;
begin
  if (Assigned(pData)) then
    Result := True
  else
  begin
    Result := False;
    exit;
  end;
  glGenTextures(1, @Texture);
  glBindTexture(GL_TEXTURE_2D, Texture);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  {Texture blends with object background}
//  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);  {Texture does NOT blend with object background}
//  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);  {Texture does NOT blend with object background}
//  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  {Texture does NOT blend with object background}
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); { only first two can be used }
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); { all of the above can be used }
//  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pData);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData);  // Use when not wanting mipmaps to be built by openGL
end;
{$ENDREGION}

{$REGION 'gen planet texture'}
procedure TPlanet.Generate_Planetar_Texture(a,b,c:TPoint;var tex,tex_c,tex_a:Cardinal);
var
  i,j,ws,hs:integer;        {для циклов}
  TA:array of byte;
  CA:array of byte;
  Clr:Trgb;
  vx,vy:TPoint;
  S:Pointer;
  F,t:single;
begin 
 ws:=tex_size;
 hs:=tex_size;
 SetLength(TA,ws*(hs+1)*4);
 SetLength(CA,ws*(hs+1)*4);
 ws:=256;
 hs:=256;
 vx:=multi(minus(b,a),1/hs);
 vy:=multi(minus(c,a),1/ws);
 For j:=0 to hs do {проходим все строки}
  For i:=0 to ws do {элементы в строке}
  begin
   f:=Get_H(tip,multi(Normalize(plus(plus(a,multi(vx,i)),multi(vy,j))),Rad));
   clr:=Get_CLR(tip,f,f);
   TA[i*4+(j)*ws*4+0]:=Clr[0];//+Random(5)-2;
   TA[i*4+(j)*ws*4+1]:=Clr[1];//+Random(5)-2;
   TA[i*4+(j)*ws*4+2]:=Clr[2];//+Random(5)-2;
   TA[i*4+(j)*ws*4+3]:=255;
   clr:=Get_CLR(tip+10,f,Get_C(tip,multi(Normalize(plus(plus(a,multi(vx,i)),multi(vy,j))),Rad)));
   CA[i*4+(j)*ws*4+0]:=Clr[0];//+Random(5)-2;
   CA[i*4+(j)*ws*4+1]:=Clr[1];//+Random(5)-2;
   CA[i*4+(j)*ws*4+2]:=Clr[2];//+Random(5)-2;
   CA[i*4+(j)*ws*4+3]:=Clr[3];
  end;
 S:=TA;
 GenTexture(S,Ws,Hs,tex);
 S:=CA;
 GenTexture(S,Ws,Hs,tex_C);
         
 ws:=64;
 hs:=64;
 vx:=multi(minus(b,a),1/hs);
 vy:=multi(minus(c,a),1/ws);
 For j:=0 to hs-1 do {проходим все строки}
  For i:=0 to ws-1 do {элементы в строке}
  begin
   f:=-Normalize(plus(plus(a,multi(vx,i)),multi(vy,j)))[2];
   if f<0.1 then f:=255 else
    if f<0.7 then f:=(sin((0.7-f)/0.7*pi))*255 else
     f:=0;                          
   TA[i*4+(j)*ws*4+0]:=255;
   TA[i*4+(j)*ws*4+1]:=255;
   TA[i*4+(j)*ws*4+2]:=255;
   TA[i*4+(j)*ws*4+3]:=round(f);
  end;
 S:=TA;
 GenTexture(S,Ws,Hs,tex_A);
end;
{$ENDREGION}

{$REGION 'Gen sky texture'}
procedure TPlanet.Generate_Sky_Texture(a,b,c:TPoint;var Tex_s:Cardinal);
var
  i,j,z,ws,hs:integer;        {для циклов}
  TA:array of byte;
  p,vx,vy:TPoint;
  dc:TCoord;
  S:Pointer;
  F,t:single;
begin
 ws:=tex_size;
 hs:=tex_size;
 SetLength(TA,ws*hs*4);
{ vx:=multi(minus(b,a),1/hs);
 vy:=multi(minus(c,a),1/ws);  }
 For j:=0 to hs-1 do {проходим все строки}
  For i:=0 to ws-1 do {элементы в строке}
  begin
   //Clr[0]:=trunc(Get_S(multi(Normalize(plus(plus(a,multi(vx,i)),multi(vy,j))),1800)));
   TA[i*4+(j)*ws*4+0]:=0;
   TA[i*4+(j)*ws*4+1]:=0;
   TA[i*4+(j)*ws*4+2]:=0;
   TA[i*4+(j)*ws*4+3]:=255;
  end;
 for i := 0 to 10000 do
  begin
   p:=Point(random(300)-150,random(300)-150,random(300));
  // p:=Point(i*50,j*50,z*50);
  // p:=Point(Get_X_V(i*3,30),Get_Y_V(i*3,30),i*0.5);
   dc:=Coord(Round(p[0]*1/(p[2]/500)/500*tex_size+tex_size/2),Round(p[1]*1/(p[2]/500)/500*tex_size+tex_size/2));
   f:=1-(Get_S(p))/500;
   if f<0 then f:=0;         
   if f>1 then f:=1;

   if (dc[0]>0) and (dc[1]>0) and
      (dc[0]<tex_size) and (dc[1]<tex_size) then
    begin
     TA[dc[0]*4+(dc[1])*ws*4+0]:=00+Round(255*f);
     TA[dc[0]*4+(dc[1])*ws*4+1]:=00+Round(255*f);
     TA[dc[0]*4+(dc[1])*ws*4+2]:=00+Round(255*f);
    end;
  end;   
 S:=TA;
 GenTexture(S,Ws,Hs,tex_S);
end;

{$ENDREGION}

{$REGION 'Create_geometry'}
procedure TPlanet.Create_Geometry;
var i,j:integer;P:TPoint;
begin
 for i:=0 to pl_p do
  for j:=0 to pl_p do
  begin
   P:=Point(i-(pl_p)/2,j-(pl_p)/2,- (pl_p)/2);
   P:=Normalize(P);
   Np[(i+j*(pl_p+1))*3+0]:=P[0];
   Np[(i+j*(pl_p+1))*3+1]:=P[1];
   Np[(i+j*(pl_p+1))*3+2]:=P[2];
   P:=multi(P,Rad);
   Vp[(i+j*(pl_p+1))*3+0]:=P[0];
   Vp[(i+j*(pl_p+1))*3+1]:=P[1];
   Vp[(i+j*(pl_p+1))*3+2]:=P[2];

   Tp[(i+j*(pl_p+1))*2+0]:=i/pl_p;
   Tp[(i+j*(pl_p+1))*2+1]:=j/pl_p;
  end;
 for i:=0 to pl_size do
  for j:=0 to pl_size do
  begin
   Fp[(i+(j)*(pl_size+1))*4+0]:=(i+0)+(j+1)*(pl_p+1);
   Fp[(i+(j)*(pl_size+1))*4+1]:=(i+1)+(j+1)*(pl_p+1);
   Fp[(i+(j)*(pl_size+1))*4+2]:=(i+1)+(j)*(pl_p+1);
   Fp[(i+(j)*(pl_size+1))*4+3]:=(i+0)+(j)*(pl_p+1);
  end;
 num_faces:=(pl_size+1)*(pl_size+1);
end;
{$ENDREGION}

{$REGION 'Create'}
constructor TPlanet.Create(tip,rad:byte);
var
i,j:byte;
A,B,C:TPoint;
begin           
   AL:=1;
 seed:=Random(360);
 Self.tip:=tip;  
 Create_Noise();
 Show_Atmosphere:=true;
 Show_Clouds:=true;
 self.Rad:=rad;           
 Atmosphere_color:=Point(1,1,1);
 Create_Geometry;
 i:=0;j:=0;
 A:=Point(Vp[(i+j*(pl_p+1))*3+0],Vp[(i+j*(pl_p+1))*3+1],Vp[(i+j*(pl_p+1))*3+2]);
 i:=pl_p;j:=0;
 B:=Point(Vp[(i+j*(pl_p+1))*3+0],Vp[(i+j*(pl_p+1))*3+1],Vp[(i+j*(pl_p+1))*3+2]);
 i:=0;j:=pl_p;
 C:=Point(Vp[(i+j*(pl_p+1))*3+0],Vp[(i+j*(pl_p+1))*3+1],Vp[(i+j*(pl_p+1))*3+2]);
 Preload(5);
 Generate_Planetar_Texture(A,B,C,pTex[0],cTex[0],aTex[0]);
 A:=multi(Rotate(90,0,1,0),A);
 B:=multi(Rotate(90,0,1,0),B);
 C:=multi(Rotate(90,0,1,0),C);
 Preload(10);
 Generate_Planetar_Texture(A,B,C,pTex[1],cTex[1],aTex[1]);
 A:=multi(Rotate(90,0,1,0),A);
 B:=multi(Rotate(90,0,1,0),B);
 C:=multi(Rotate(90,0,1,0),C);
 Preload(20);
 Generate_Planetar_Texture(A,B,C,pTex[2],cTex[2],aTex[2]);
 A:=multi(Rotate(90,0,1,0),A);
 B:=multi(Rotate(90,0,1,0),B);
 C:=multi(Rotate(90,0,1,0),C);
 Preload(30);
 Generate_Planetar_Texture(A,B,C,pTex[3],cTex[3],aTex[3]);
 A:=multi(Rotate(90,0,0,1),A);
 B:=multi(Rotate(90,0,0,1),B);
 C:=multi(Rotate(90,0,0,1),C);
 Preload(40);
 Generate_Planetar_Texture(A,B,C,pTex[4],cTex[4],aTex[4]);
 A:=multi(Rotate(180,0,0,1),A);
 B:=multi(Rotate(180,0,0,1),B);
 C:=multi(Rotate(180,0,0,1),C);
 Preload(50);
 Generate_Planetar_Texture(A,B,C,pTex[5],cTex[5],aTex[5]);
 Generate_Sky_Texture(A,B,C,sTex[0]);
 Preload(60);
 Generate_Sky_Texture(A,B,C,sTex[1]);
 Generate_Sky_Texture(A,B,C,sTex[2]);
 Preload(70);
 Generate_Sky_Texture(A,B,C,sTex[3]);
 Generate_Sky_Texture(A,B,C,sTex[4]);
 Preload(80);
 Generate_Sky_Texture(A,B,C,sTex[5]);
 ang_s:=0.01;
 for i:=0 to 25 do
  pts[i]:=Point(Random(160)-80,Random(360),0);
 for i:=0 to 25 do
  ptip[i]:=Random(3)+1;
 Preload(90);

end;
{$ENDREGION}

{$REGION 'Render'}
procedure TPlanet.Draw_Planet(var pTex:TCube_map);
begin
 glBindTexture(GL_Texture_2d,pTex[0]);
 glDrawElements(GL_QUADS, (num_faces)*4, GL_UNSIGNED_INT, @Fp[0]);
 glRotatef(90,0,1,0);
 glBindTexture(GL_Texture_2d,pTex[1]);
 glDrawElements(GL_QUADS, (num_faces)*4, GL_UNSIGNED_INT, @Fp[0]);
 glRotatef(90,0,1,0);
 glBindTexture(GL_Texture_2d,pTex[2]);
 glDrawElements(GL_QUADS, (num_faces)*4, GL_UNSIGNED_INT, @Fp[0]);
 glRotatef(90,0,1,0);
 glBindTexture(GL_Texture_2d,pTex[3]);
 glDrawElements(GL_QUADS, (num_faces)*4, GL_UNSIGNED_INT, @Fp[0]);
 glRotatef(90,1,0,0);
 glBindTexture(GL_Texture_2d,pTex[4]);
 glDrawElements(GL_QUADS, (num_faces)*4, GL_UNSIGNED_INT, @Fp[0]);
 glRotatef(180,-1,0,0);
 glBindTexture(GL_Texture_2d,pTex[5]);
 glDrawElements(GL_QUADS, (num_faces)*4, GL_UNSIGNED_INT, @Fp[0]);
end;

procedure TPlanet.Render;
var
 i,j:byte;
 ang,a,b:Single;
begin
//move
 Self.ang:=Get_R(Self.ang+Self.ang_s);

 glEnable(GL_BLEND);     
//glDisable(GL_Texture_2d);
 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_NORMAL_ARRAY);
 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 glNormalPointer(GL_FLOAT, 0, @Np[0]);
 glTexCoordPointer(2, GL_FLOAT, 0, @Tp[0]);
 glVertexPointer(3, GL_FLOAT, 0, @Vp[0]);

 glDisable(GL_Depth_Test);

 //sky box
 glColor4f(5,5,5,1);
 glDisable(GL_LIGHTING);
 glCullFace(gl_Back);
 glPushMatrix();
  glScalef(30,30,30);
  Draw_Planet(sTex);
 glPopMatrix;
 glCullFace(gl_Front);
glEnable(GL_LIGHTING);
glColor4f(1,1,1,1);
 If Show_Atmosphere then
 begin
  //atmosphere halo
  ang:=arccos(Rad/(AL+10))/pi*180;
  a:=Get_Y_V(ang,1);
  b:=Get_X_V(ang,1);
  glDisable(GL_Texture_2d);
  glPushMatrix();
   glRotatef(AY,0,0,-1); //rotate
   glRotatef(AX,-1,0,0);
   glBegin(gl_Quad_Strip);
   for i:= 0 to 36 do
     begin
      glNormal3f(a*Get_X_V(i*10,1),a*Get_Y_V(i*10,1),-b*1);
      glColor4f(Atmosphere_color[0],Atmosphere_color[1],Atmosphere_color[2],0);
      glVertex3f(a*Get_X_V(i*10,Self.Rad*1.07),a*Get_Y_V(i*10,Self.Rad*1.07),-b*Rad);
      glColor4f(Atmosphere_color[0],Atmosphere_color[1],Atmosphere_color[2],1);
      glVertex3f(a*Get_X_V(i*10,Self.Rad*0.95),a*Get_Y_V(i*10,Self.Rad*0.95),-b*Rad);
     end;
   glend;
  glPopMatrix;
 end;
//planet   
glColor3f(5,5,5);
glEnable(GL_Texture_2d);
 glPushMatrix();
  glRotateF(Self.ang,0,0,1);
  Draw_Planet(pTex);
 glPopMatrix;
 if Show_Clouds then
 begin
  glPushMatrix();   
  glRotateF(Self.ang,0,0,1);
   //clouds
   glColor4f(0,0,0,0.6);
   Draw_Planet(cTex);
  glPopMatrix;
  glPushMatrix();     
   glRotateF(Self.ang,0,0,1);
   glScalef(1.01,1.01,1.01);
   glColor4f(1,1,1,1);
   Draw_Planet(cTex);
  glPopMatrix;
 end;
 If Show_Atmosphere then
 begin   
  glPushMatrix();
   //atmosphere
   glColor4f(Atmosphere_color[0],Atmosphere_color[1],Atmosphere_color[2],(350-AL)/220);
   glRotatef(AY,0,0,-1); //rotate
   glRotatef(AX,-1,0,0);
   glScalef(1.012,1.012,1.012);
   Draw_Planet(aTex);
  glPopMatrix;
 end;
glDisable(GL_Lighting);
for i:=0 to 25 do
 begin
  glpushmatrix();         
  glRotateF(Self.ang,0,0,1);
  glrotatef(pts[i][1],0,0,1);
  glrotatef(pts[i][0],1,0,0);
  glbegin(GL_Triangle_fan);
 // glColor4f(clr[i][0],clr[i][1],clr[i][2],1);
  glColor4f(1,0,0,0.5);
  glVertex3f(0,rad+0.01,0);
  for j:=0 to 6 do
    begin
     glVertex3f(-Get_X_V(j*60,0.2),rad+0.01,Get_y_V(j*60,0.2));
    end;
  glend;
  glpopmatrix();
 end;
 glEnable(GL_Depth_Test);
 glDisableClientState(GL_VERTEX_ARRAY);
 glDisableClientState(GL_NORMAL_ARRAY);
 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 glCullFace(gl_Back);
 glloadidentity();
 glbegin(GL_Quads);
 glColor4f(1,1,1,0.2);
 glVertex3f( 0.5, 0,0);
 glVertex3f( 0, 0.5,0);
 glVertex3f(-0.5, 0,0);
 glVertex3f( 0,-0.5,0);
 glend;
 for i:=0 to 25 do
  if (pts[i][1]+4>Get_R(-AY+180-Self.ang)) and (pts[i][1]-4<Get_R(-AY+180-Self.ang)) then
  if (pts[i][0]+4>(+AX-90)) and (pts[i][0]-4<(+AX-90)) then
  begin
   case ptip[i] of
    1:World.Show_message('Захват сектора');
    2:World.Show_message('Десантная операция');
    3:World.Show_message('Штурм');
   end;
   if  mbl then
   begin
    AL:=1;
    world.gen_random_level(ptip[i]);
    exit;
   end;
  end;      
   case Random(10000) of
    1:World.Show_message('Аналитики прогнозируют скорую победу в течении 200 лет.');
    2:World.Show_message('Разведка сообщает об ударе зеленых в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    3:World.Show_message('Разведка сообщает об ударе красных в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    4:World.Show_message('Разведка сообщает об ударе желтых в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    5:World.Show_message('Аналитики прогнозируют скорую победу в течении 200 лет.');
    6:World.Show_message('Аналитики прогнозируют скорую победу в течении 200 лет.');
    7:World.Show_message('Успешно завершена десантная операция. Выживших нет.');
    8:World.Show_message('Потерян сектор '+inttostr(Random(250))+' '+inttostr(Random(250)));
    9:World.Show_message('Успешно завершена тайная операция.');
    10:World.Show_message('Зеленые активизировались в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    11:World.Show_message('Красные активизировались в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    12:World.Show_message('Желтые активизировались в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    13:World.Show_message('Захвачен военный завод '+inttostr(Random(2500)));
    14:World.Show_message('Захвачен военный завод зеленых.');
    15:World.Show_message('Захвачен военный завод красных.');
    16:World.Show_message('Захвачен военный завод желтых.');
    17:World.Show_message('Фабрика красных остановлена на 2000 тактов.');
    18:World.Show_message('Фабрика зеленых остановлена на 2000 тактов.');
    19:World.Show_message('Фабрика желтых остановлена на 2000 тактов.');
    20:World.Show_message('Частота десантных операций противника увеличивается');
    21:World.Show_message('Развернуты дополнительные мощности в секторе '+inttostr(Random(250))+' '+inttostr(Random(250)));
    22:World.Show_message('Ресурсы сектора '+inttostr(Random(250))+' '+inttostr(Random(250))+' исчерпаны.');
   end;
end;
{$ENDREGION}

end.
