import Vertex3D;

public class PlaneEqn {
    //template: Image[] xo_sprites = new Image[2];
    private double alpha_ABC[] = new double[3];
    private double   red_ABC[] = new double[3];
    private double green_ABC[] = new double[3];
    private double  blue_ABC[] = new double[3];
    public float Area;
       
    // Constructor
    public PlaneEqn(Vertex3D v0, Vertex3D v1, Vertex3D v2)
    {
        
        // Compute the area of the triangle, using determinant
        //
        //  | A B C |
        //  | D E F | = AEI + BFG + CDH - (AFH - BDI - CEG) 
        //  | G H I |
        //
        // Therefore...
        //
        //              | x0 x1 x2 |
        //  Area = .5 * | y0 y1 y2 | = .5 * (x0*y1 + x1*y2 + x2*y0 - (x0*y2 + x1*y0 + x2*y1)) 
        //              |  1  1  1 |
        
        Area = (float) 0.5 * (v0.x * v1.y + v1.x * v2.y + v2.x * v0.y -
                             (v0.x * v2.y + v1.x * v0.y + v2.x * v1.y));
        
        double scale = 1 / (2 * (double) Area);
        
        int t0 = v0.argb;
        int t1 = v1.argb;
        int t2 = v2.argb;
        double sp0, sp1, sp2;
        double Ap, Bp, Cp;
        
        //////////////////////////
        // Fill in ABC matrices //
        //////////////////////////
        
        // 31      23      15      7       0
        // +-------------------------------+
        // | alpha |  red  | green | blue  |
        // +-------------------------------+
        
        //-------------------
        // Fill in blue_ABC[]
        //-------------------
        // Pull blue bits out and multiply by 1/(2Area)
        sp0 = scale * (t0 & 255); 
        sp1 = scale * (t1 & 255);
        sp2 = scale * (t2 & 255);
        // Compute A, B, and C
        Ap = ( ((v1.y - v2.y) * sp0) + ((v2.y - v0.y) * sp1) + ((v0.y - v1.y) * sp2) );
        Bp = ( ((v2.x - v1.x) * sp0) + ((v0.x - v2.x) * sp1) + ((v1.x - v0.x) * sp2) );
        Cp = ( (( (v1.x * v2.y) - (v2.x * v1.y) ) * sp0) +
               (( (v2.x * v0.y) - (v0.x * v2.y) ) * sp1) +
               (( (v0.x * v1.y) - (v1.x * v0.y) ) * sp2) );
        // Store into blue_ABC[]
        blue_ABC[0] = Ap;
        blue_ABC[1] = Bp;
        blue_ABC[2] = Cp;
        // Modify t0, t1, and t2
        t0 >>= 8; t1 >>= 8; t2 >>= 8;
        
        //-------------------
        // Fill in green_ABC[]
        //-------------------
        // Pull green bits out and multiply by 1/(2Area)
        sp0 = scale * (t0 & 255); 
        sp1 = scale * (t1 & 255);
        sp2 = scale * (t2 & 255);
        // Compute A, B, and C
        Ap = ( ((v1.y - v2.y) * sp0) + ((v2.y - v0.y) * sp1) + ((v0.y - v1.y) * sp2) );
        Bp = ( ((v2.x - v1.x) * sp0) + ((v0.x - v2.x) * sp1) + ((v1.x - v0.x) * sp2) );
        Cp = ( (( (v1.x * v2.y) - (v2.x * v1.y) ) * sp0) +
               (( (v2.x * v0.y) - (v0.x * v2.y) ) * sp1) +
               (( (v0.x * v1.y) - (v1.x * v0.y) ) * sp2) );
        // Store into green_ABC[]
        green_ABC[0] = Ap;
        green_ABC[1] = Bp;
        green_ABC[2] = Cp;
        // Modify t0, t1, and t2
        t0 >>= 8; t1 >>= 8; t2 >>= 8;
        
        //-------------------
        // Fill in red_ABC[]
        //-------------------
        // Pull red bits out and multiply by 1/(2Area)
        sp0 = scale * (t0 & 255); 
        sp1 = scale * (t1 & 255);
        sp2 = scale * (t2 & 255);
        // Compute A, B, and C
        Ap = ( ((v1.y - v2.y) * sp0) + ((v2.y - v0.y) * sp1) + ((v0.y - v1.y) * sp2) );
        Bp = ( ((v2.x - v1.x) * sp0) + ((v0.x - v2.x) * sp1) + ((v1.x - v0.x) * sp2) );
        Cp = ( (( (v1.x * v2.y) - (v2.x * v1.y) ) * sp0) +
               (( (v2.x * v0.y) - (v0.x * v2.y) ) * sp1) +
               (( (v0.x * v1.y) - (v1.x * v0.y) ) * sp2) );
        // Store into red_ABC[]
        red_ABC[0] = Ap;
        red_ABC[1] = Bp;
        red_ABC[2] = Cp;
        // Modify t0, t1, and t2
        t0 >>= 8; t1 >>= 8; t2 >>= 8;

        //--------------------
        // Fill in alpha_ABC[]
        //--------------------
        // Pull alpha bits out and multiply by 1/(2Area)
        sp0 = scale * (t0 & 255); 
        sp1 = scale * (t1 & 255);
        sp2 = scale * (t2 & 255);
        // Compute A, B, and C
        Ap = ( ((v1.y - v2.y) * sp0) + ((v2.y - v0.y) * sp1) + ((v0.y - v1.y) * sp2) );
        Bp = ( ((v2.x - v1.x) * sp0) + ((v0.x - v2.x) * sp1) + ((v1.x - v0.x) * sp2) );
        Cp = ( (( (v1.x * v2.y) - (v2.x * v1.y) ) * sp0) +
               (( (v2.x * v0.y) - (v0.x * v2.y) ) * sp1) +
               (( (v0.x * v1.y) - (v1.x * v0.y) ) * sp2) );
        // Store into alpha_ABC[]
        alpha_ABC[0] = Ap;
        alpha_ABC[1] = Bp;
        alpha_ABC[2] = Cp;
    }
    
    public int get_argb(float x, float y)
    {
        
        // 31      23      15      7       0
        // +-------------------------------+
        // | alpha |  red  | green | blue  |
        // +-------------------------------+
       
        int a = (int) ( alpha_ABC[0]*x + alpha_ABC[1]*y + alpha_ABC[2] + 0.5);
        int r = (int) (   red_ABC[0]*x +   red_ABC[1]*y +   red_ABC[2] + 0.5);
        int g = (int) ( green_ABC[0]*x + green_ABC[1]*y + green_ABC[2] + 0.5);
        int b = (int) (  blue_ABC[0]*x +  blue_ABC[1]*y +  blue_ABC[2] + 0.5);
        
        a = a & 255;
        r = r & 255;
        g = g & 255;
        b = b & 255;

        a <<= 24;
        r <<= 16;
        g <<= 8;
        
        int argb = a+r+g+b;

        return (argb);
        
        //return ( (255 << 24) + (246<<16) + (29<<8) + 8 ); // RED
    }
}
