
#define MAX_STEPS 80
#define MAX_DIST 60.
#define SURF_DIST .005
#define PI2 = 6.28318


mat2 Rot(float a) {
    float s=sin(a), c=cos(a);
    return mat2(c, -s, s, c);
}

vec3 RotTPR(vec3 p,float a,float b,float c)
{
    p.xz *= Rot(a);   p.yz *= Rot(b);   p.xy *= Rot(c);
    return p;
}
float sdSegment(vec3 p,vec3 a,vec3 b,float R)
{
    float h = min(1.0,
                max(0.0,
                dot(p-a,b-a) / dot(b-a,b-a)));

    return length(p-a-(b-a)*h)-R;
    
}

float sdBox(vec3 p , vec3 s){
  
    p = abs(p)-s;  
    return length(max(p, 0.))+min(max(p.x, max(p.y, p.z)), 0.);
}
float sdSquareFrame3(vec3 p, vec3 bOut,vec3 bIn)
{
    float dist = 1000.0;
        dist = min(dist, sdBox(p,bOut));
        dist = max(dist, -sdBox(p,bIn));

    return dist;
}
float sdBoxFrame3(vec3 p, vec3 bOut,vec3 bIn)
{
    float dist = 1000.0;
        dist = min(dist, sdBox(p,bOut));
        dist = max(dist, -sdBox(p,bIn));

    return dist;
}

float sdAxisLines(vec3 p, float segLen, vec3 position ,float spRadius)
{
    p += position;
    float dist = 1000.0;
   
    vec3 k1 = vec3(segLen,0,0),k2=vec3(0,segLen,0),k3=vec3(0,0,segLen); 
    dist= min(dist,sdSegment (p,k1,-k1,0.03));
    dist= min(dist,sdSegment (p,k2,-k2,0.03));
    dist= min(dist,sdSegment (p,k3,-k3,0.03));
    //sphere
   dist= min(dist,length(p) - spRadius);
   p.y-=spRadius;
   dist= min(dist,length(p) - 0.3);
    vec3 offs = vec3(0.0,1.6,0.0);
    vec3 boxSize = vec3(1.3,0.5,1.2);
      dist=min(dist,sdBox( p+offs , boxSize));
 return dist;


}

float getCordaLen(float radius ,float sides, out float outAddRadius){
    
    float phi = 6.283185307/(sides*2.0);  //half angle
    float x = radius - radius * cos(phi);
    x *= x;
    float y = radius*sin(phi);
    y*=y;
    //out-variable
    outAddRadius =sqrt(radius*radius-y );
   float len= sqrt(x+y);
    
    return len;
 }

float sdPoly(vec3 p, float sides, float radius)
{
    float theta = 6.283185307/sides;
    float dist =1000.0;  
    vec3 p1 =p; vec3 p2;
    float sphereRadius = radius;
  
    //rotate space  
     p1.xy *= Rot(-0.15*iTime); //roll+0.7853980.785398+
     p1.yz *= Rot( 0.4); //phi
    

     float width = 0.415;float thic =0.1;
     
     float outAddRadius = 0.0;//+thic
     float len =  getCordaLen (sphereRadius+thic +thic, sides, outAddRadius);
     float translateDist = outAddRadius+thic;
     vec3 boxSize = vec3( thic, width, len);
    
      for(float i=1.0; i<sides +1.0;i++)
      {
           p2=p1;
         
           p2.xz *= Rot(0.50*iTime + i * theta);//rotate theta in local space
           p2.x -= translateDist;
             
           dist  = min(dist,sdBox(p2,boxSize));
          
           //p2.x += translateDist+translateDist;
           //dist  = min(dist,sdBox(p2,boxSize));
             
      }
   
    return dist;


}


float counter=0.0;
 //Coordinat lines, sphere, polygon 
float Sceen(vec3 p)
{
    float dist =1000.0;   float sphereRadius = 1.;  
    float segLen= sphereRadius+1.4 ;//, outT;
                   
    vec3 p1 =p; vec3 p2;
    
    float sides = 5.0;
    
    sides=floor(sides);
    dist = min(dist,sdAxisLines(p,segLen,vec3(0.0),sphereRadius));
    dist = min(dist,sdPoly( p, sides , 3.0));
   
    return dist;
}
//Outer frame and planet orbiter
float Sceen2(vec3 p)
{

    float dist =1000.0;   float radius = 1.;  
    float segLen= radius+.80; float radius2 = 5.8;//+0.5*iTime
    float width = .35;
     vec3 spO =vec3( radius2,width, radius2);
     
     vec3 boxOut = vec3( radius2,width, radius2);
     vec3 boxIn = vec3( radius2-width*0.5,width+width, radius2-width*0.5);
    vec3 p1 =p; vec3 p2;

    //rotate frame localspace 
    p1=p;
   
    p1.xy *= Rot(iTime*0.034 ); //roll1
    p1.yz *= Rot(0.392699 ); //phi 
  
    p1.xz *= Rot(iTime*0.08 );//tetha 0.628318
   dist = min(dist, sdSquareFrame3( p1,  boxOut, boxIn));
  
    vec3 posOrb=p1; //inherit rot so planets follow the frame
   vec3 posOrb2 = p1;  
   vec3 posOrb3 = p1;
    posOrb.xz *=Rot(-0.785398); //rotate -45 deg relative frame
    posOrb.x +=  radius2 * 1.414;// translate in the rotated x direction
    posOrb.xy *= Rot(iTime); //roll
    posOrb.x +=2.0 +cos(iTime )+1.0;
    dist= min(dist ,length(posOrb)-0.2); //planet orbiting frame
    ///////////////////////////////////
    posOrb2.xz *=Rot(0.785398); //rotate 45 deg relative frame
    posOrb2.x +=  radius2 * 1.414;//9.195; // translate in the rotated x direction
    posOrb2.xy *= Rot(iTime); //roll
    posOrb2.x +=1.50;
    dist= min(dist ,length(posOrb2)-0.15); //planet orbiting frame
    ///////////////////////////
    
    
    posOrb3.x +=  -radius2 ;//9.195; // translate in the rotated x direction
    posOrb3.xy *= Rot(iTime*1.); //roll
   
    posOrb3.x += 1.7;
    
    posOrb3.xy *= Rot(-iTime*1.);//undo last rotation
    posOrb3.xz *= Rot(0.523598);//tilt moon orbit
    
     
    posOrb3.yz *= Rot(-iTime*4.5);
    dist= min(dist ,length(posOrb3)-0.4); //planet orbiting frame 
    //dist= min(dist ,sdBox(posOrb3 , vec3 (0.4)));
  
    posOrb3.y +=0.9;
    dist= min(dist ,length(posOrb3)-0.1); //moon orbiting
    
return dist;
}
//Inner frame
float SceenTPR(vec3 p)  //Order of rotation tetha phi rho
{

    float dist =1000.0;  
    float radius2 = 4.0;
    float width = 0.2;

    vec3 boxOut = vec3( radius2 ,radius2,  width  );
    vec3 boxIn = vec3( radius2-width*0.5,  radius2-width*0.5 ,width+width );
  
    // Angles 
    float tetha = 0.51,
          phi   = 0.8785398,
          rho   = -0.5*iTime;
   

 
   p = RotTPR( p,tetha,phi,rho);
   
   dist = min(dist, sdSquareFrame3( p,  boxOut, boxIn));
     
    
return dist;
}


float GetDist(vec3 p) {
       
       float d=1000.0;
       d= min(d,Sceen(p));    //Coordinat lines, sphere, n sided polygon
       d= min(d,Sceen2(p));   //Outer frame
       //d= min(d,SceenTPR(p)); //Inner frame
    
    return d;
}

float RayMarch(vec3 ro, vec3 rd) {
	float dO=0.;
    
    for(int i=0; i<MAX_STEPS; i++) {
    	vec3 p = ro + rd*dO;
        float dS = GetDist(p);
        dO += dS;
        if(dO>MAX_DIST || abs(dS)<SURF_DIST) break;
    }
    
    return dO;
}

vec3 GetNormal(vec3 p) {
	float d = GetDist(p);
    vec2 e = vec2(.001, 0);
    
    vec3 n = d - vec3(
        GetDist(p-e.xyy),
        GetDist(p-e.yxy),
        GetDist(p-e.yyx));
    
    return normalize(n);
}

vec3 GetRayDir(vec2 uv, vec3 p, vec3 l, float z) {
    vec3 f = normalize(l-p),
        r = normalize(cross(vec3(0,1,0), f)),
        u = cross(f,r),
        c = f*z,
        d = normalize( c + uv.x*r + uv.y*u);
    return d;
}
float GetLight(vec3 p) {
    
    vec3 lightPos = vec3(9, 13, 20);
    //lightPos.xz += vec2(sin(iTime), cos(iTime))*2.;
    vec3 lig = normalize(lightPos-p);
    vec3 n = GetNormal(p);
    
    float dif = clamp(dot(n, lig), 0.0, 1.);
   
    float d = RayMarch(p+n*SURF_DIST*2., lig);
    if(d<length(lightPos-p)) dif *= .2;
   
    return dif;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;
	vec2 m = iMouse.xy/iResolution.xy;

    vec3 ro = vec3(2.0, 1.0, -45.0);
    ro.yz *= Rot(-m.y*1.9+1.5);
    ro.xz *= Rot(-m.x*6.2831);
  
    vec3 rd = GetRayDir(uv, ro, vec3(0,0.,0), 3.0);
   
    vec3 col = vec3(0.); 
    vec2 nuv= -uv;
    
    //col=vec3(nuv.y,nuv.y, nuv.y);      
    //col=vec3(0.52-nuv.y-0.1, 0.01-nuv.y+0.1 , 0.2+ nuv.y);
    //col=vec3(0.4-nuv.y-0.1, 0.05-nuv.y , 0.5- nuv.y*0.2);//+ nuv.y*0.1)
    col=vec3(-uv.y*0.5 +.5,-uv.y,.3);
    float d = RayMarch(ro, rd);

    if(d<MAX_DIST) {
        vec3 p = ro + rd * d;
        float dif=GetLight( p);
        col = vec3(0.95*dif,dif,0.9*dif);
    }
   
    fragColor = vec4(col,1.0);
 
}