//-----Illuminate Script-----
//Script intended for use in CodeLab in Paint.NET
//This script was made by Spikehead777
//You may use this script for free and personal use, but you cannot sell it.
//It's free. No one can steal it, no one can sell it, no one has to use it, but anybody can use it.
double Amount1=1;	//[-10000,10000]Height Scale
double Amount2=90;	//[-180,180]Direction
double Amount3=45;	//[0,90]Elevation

//Don't know what this does =P
void Render(Surface dst, Surface src, Rectangle rect)
{
    //Get the vector of the lightsource and store it
    double Xn,Yn,Zn,m,I;
    Xn = Math.Cos((Math.PI/180) * Amount2) * Math.Cos((Math.PI/180) * Amount3);
    Yn = -Math.Sin((Math.PI/180) * Amount2) * Math.Cos((Math.PI/180) * Amount3);
    Zn = Math.Sin((Math.PI/180) * Amount3);
    
    // Delete any of these lines you don't need
    //Also don't know what this does =P
    Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    
    //Coordinate triples for each of the pixels in the 2x2 square (X,Y,Intensity)
    int xnn,xnp,xpn,xpp;
    int ynn,ynp,ypn,ypp;
    double znn,znp,zpn,zpp;
    
    //Coordinate triples that are used for calculating the normals
    int x1,x2,x3,x4;
    int y1,y2,y3,y4;
    double z1,z2,z3,z4;
    
    //Edge Positions and Size
    int L,R,T,B,W,H;
    L = selection.Left;
    R = selection.Right;
    T = selection.Top;
    B = selection.Bottom;
    W = R-L;
    H = B-T;
    
    //Normal vectors of the 2x2 square (4 are used for smoothness)
    double X1,Y1,Z1;
    double X2,Y2,Z2;
    double X3,Y3,Z3;
    double X4,Y4,Z4;
    
    //Average of the above normals
    double Nx,Ny,Nz;
    
    //Iterate through each y-pixel in the image
    for(int y = T; y < B; y++)
    {
        //Get the y-coordinates for each of the pixels in a 2x2 square
        ynn = y;ynp = y+1;ypn = y;ypp = y+1;
        
        //Wraps coordinates if it results in the square crossing the edge
        if (ynp >= B) ynp -= H;
        if (ypp >= B) ypp -= H;
        if (ynn < T) ynn += H;
        if (ypn < T) ypn += H;
        
        //Iterate through each y-pixel in the image
        for (int x = L; x < R; x++)
        {
            //Get the x-coordinates for each of the pixels in a 2x2 square
            xnn = x;xnp = x;xpn = x+1;xpp = x+1;
            
            //Wraps coordinates if it results in the square crossing the edge
            if (xpn >= R) xpn -= W;
            if (xpp >= R) xpp -= W;
            if (xnn < L) xnn += W;
            if (xnp < L) xnp += W;
            
            //Get the intensity of each pixel at each position in the 2x2 square, and scale it up/down
            znn = src[xnn,ynn].R*(Amount1/100);
            znp = src[xnp,ynp].R*(Amount1/100);
            zpn = src[xpn,ypn].R*(Amount1/100);
            zpp = src[xpp,ypp].R*(Amount1/100);
            
            //Psuedo Coordinates (For calculating the Normals)
            x1 = x  ;y1 = y  ;z1 = znn;
            x2 = x  ;y2 = y+1;z2 = znp;
            x3 = x+1;y3 = y+1;z3 = zpp;
            x4 = x+1;y4 = y  ;z4 = zpn;
            
            //First normal
            X1 = (y3-y1)*(z2-z1)-(y2-y1)*(z3-z1);
            Y1 = (z3-z1)*(x2-x1)-(z2-z1)*(x3-x1);
            Z1 = (x3-x1)*(y2-y1)-(x2-x1)*(y3-y1);
            
            //Second Normal
            X2 = (y4-y2)*(z3-z2)-(y3-y2)*(z4-z2);
            Y2 = (z4-z2)*(x3-x2)-(z3-z2)*(x4-x2);
            Z2 = (x4-x2)*(y3-y2)-(x3-x2)*(y4-y2);
            
            //Third Normal
            X3 = (y1-y3)*(z4-z3)-(y4-y3)*(z1-z3);
            Y3 = (z1-z3)*(x4-x3)-(z4-z3)*(x1-x3);
            Z3 = (x1-x3)*(y4-y3)-(x4-x3)*(y1-y3);
            
            //Fourth Normal
            X4 = (y2-y4)*(z1-z4)-(y1-y4)*(z2-z4);
            Y4 = (z2-z4)*(x1-x4)-(z1-z4)*(x2-x4);
            Z4 = (x2-x4)*(y1-y4)-(x1-x4)*(y2-y4);
            
            //Average of above normals
            Nx = (X1+X2+X3+X4);
            Ny = (Y1+Y2+Y3+Y4);
            Nz = (Z1+Z2+Z3+Z4);
            
            //Normalize the average (Make the vector length equal to 1)
            m = Math.Sqrt((Nx*Nx)+(Ny*Ny)+(Nz*Nz));
            Nx /= m;Ny /= m;Nz /= m;
            
            //Get the intensity of the normal with respect to the light source vector
            I = ((Xn*Nx)+(Yn*Ny)+(Zn*Nz))*255;
            
            //Assign the pixels
            dst[x,y] = ColorBgra.FromBgr(
                Utility.ClampToByte(I),
                Utility.ClampToByte(I),
                Utility.ClampToByte(I));
        }
    }
}
