
/*
 * Java Rubik's Cube
 * -----------------
 *
 * Copyright 1996, Song Li  
 * URL: www.cs.umbc.edu/~sli2
 *
 * 
 * You can use the code for any nonprofittable use. But remember to mention
 * the authors' names in your revised program. You are also encouraged to
 * improve the program or give your comments and bug reports. If there are
 * further questions, please contact me and I'll be glad to help. My E-Mail
 * address is: sli2@gl.umbc.edu.
 *
 */



import java.awt.* ;



class CubeFace extends Face {
    
    int   Height ;
    int   Width ;
    Color ColorMap [] [] ;

    int   SquareX [] = new int [4] ;
    int   SquareY [] = new int [4] ;
    int   MapX [] [] ;
    int   MapY [] [] ;


    CubeFace (int height, int width) {
        super (4) ;
        Height = height ;
        Width  = width ;

        ColorMap = new Color [Height] [Width] ;
        MapX     = new int [Height+1] [Width+1] ;
        MapY     = new int [Height+1] [Width+1] ;
    }
    
    
    void SetMap (Color map [] []) {
        for (int i=0; i<Height; i++)
            for (int j=0; j<Width; j++)
                ColorMap [i] [j] = map [i] [j] ;
    }
    

    void SetMap (Color color, int height, int width) {
        ColorMap [height] [width] = color ;
    }



    public float Unproject (float x, float y) {
    
        float x1=ScreenVer[1].x, y1=ScreenVer[1].y, z1=ScreenVer[1].z ;
        float x2=ScreenVer[2].x, y2=ScreenVer[2].y, z2=ScreenVer[2].z ;
        float x3=ScreenVer[3].x, y3=ScreenVer[3].y, z3=ScreenVer[3].z ;
        
        float A11, A12, A13 ;
        float A21, A22, A23 ;
        float A31, A32, A33 ;
        
        A11 = y2*z3 - z2*y3 ;
        A12 = z2*x3 - x2*z3 ;
        A13 = x2*y3 - y2*x3 ;
        A21 = z1*y3 - y1*z3 ;
        A22 = x1*z3 - z1*x3 ;
        A23 = y1*x3 - x1*y3 ;
        A31 = y1*z2 - z1*y2 ;
        A32 = z1*x2 - x1*z2 ;
        A33 = x1*y2 - y1*x2 ;
        
        float det = x1*A11 + y1*A12 + z1*A13 ;
        
        float a = A11 + A21 + A31 ;
        float b = A12 + A22 + A32 ;
        float c = A13 + A23 + A33 ;
        
        return (det-a*x-b*y) / c ;
    }
    




    public void Paint (Graphics graph, int width, int height) {
        int h, w ;

        for (int i=0; i<VerNum; i++) {
            ScreenX [i] = (int) ScreenVer[i].x + width/2 ;
            ScreenY [i] = height/2 - (int) ScreenVer[i].y ;
            }

        float deltaxx = (float) (ScreenX[1]-ScreenX[0]) / Width  ;
        float deltaxy = (float) (ScreenY[1]-ScreenY[0]) / Width  ;
        float deltayx = (float) (ScreenX[3]-ScreenX[0]) / Height ;
        float deltayy = (float) (ScreenY[3]-ScreenY[0]) / Height ;


        for (h=0; h<=Height; h++)
            for (w=0; w<=Width; w++) {
                MapX[h][w] = (int) (ScreenX[0] + w * deltaxx + h * deltayx + 0.5) ;
                MapY[h][w] = (int) (ScreenY[0] + w * deltaxy + h * deltayy + 0.5) ;
                }
        

        for (h=0; h<Height; h++)
            for (w=0; w<Width; w++) {
                SquareX [0] = MapX [h  ] [w  ] ;
                SquareX [1] = MapX [h  ] [w+1] ;
                SquareX [2] = MapX [h+1] [w+1] ;
                SquareX [3] = MapX [h+1] [w  ] ;

                SquareY [0] = MapY [h  ] [w  ] ;
                SquareY [1] = MapY [h  ] [w+1] ;
                SquareY [2] = MapY [h+1] [w+1] ;
                SquareY [3] = MapY [h+1] [w  ] ;

                graph.setColor (ColorMap [h] [w]);
                graph.fillPolygon (SquareX, SquareY, 4);
            }


        graph.setColor (Color.black);

        for (h=0; h<=Height; h++)
            graph.drawLine (
                (int) (ScreenX[0] + h * deltayx + 0.5),
                (int) (ScreenY[0] + h * deltayy + 0.5),
                (int) (ScreenX[1] + h * deltayx + 0.5),
                (int) (ScreenY[1] + h * deltayy + 0.5) ) ;
            
        for (w=0; w<=Width; w++)
            graph.drawLine (
                (int) (ScreenX[0] + w * deltaxx + 0.5),
                (int) (ScreenY[0] + w * deltaxy + 0.5), 
                (int) (ScreenX[3] + w * deltaxx + 0.5),
                (int) (ScreenY[3] + w * deltaxy + 0.5) ) ;
    }
}




