
//Title:        Computer Graphics
//Version:      
//Copyright:    Copyright (c) 1998
//Author:       Ashish
//Company:      IITD
//Description:

package Graphics;

import java.awt.*;
import java.util.*;
import javax.swing.JPanel;

public class canvas extends JPanel
{
  BorderLayout borderLayout1 = new BorderLayout();


  Vector origin=new Vector(200,200);

  Scene scene=new Scene();
  Matrix transform=new Matrix();
  double scalefactor=10;

  boolean showaxis=false;
  boolean showwireframe=false;

  boolean action_flag=false;


    int x[]=new int[1000];
    int y[]=new int[1000];



  

  


  public canvas()
  {
    try
    {
      jbInit();
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }

    this.setPreferredSize(new Dimension(600,600));

    //______Generate scene_________
    //____Add six polygons


    scene.cameraLocation.set(0,0,100);
     scene.cameraLookat.set(0,0,0);

     scene.cameraDir= scene.cameraLocation.subtract( scene.cameraLookat);
     scene.cameraDir.normalize();

    add_axis();

    // ____Now create the default scene
    //createscene();

    compute();
  }

  public void add_axis()
  {
    Object o=new Object();
    MyPolygon p;

    Random rnd=new Random();

    int x,y,z,x1,y1,z1;
    //________Draw the axes
    p=new MyPolygon();

    p.addPoint(0,0,0);
    p.addPoint(0,0,20);

    o.add_polygon(p,new Vector(1,1,1));

    p=new MyPolygon();

    p.addPoint(0,0,0);
    p.addPoint(0,20,0);

    o.add_polygon(p,new Vector(1,1,1));

    p=new MyPolygon();
     p.addPoint(0,0,0);
    p.addPoint(20,0,0);



    o.add_polygon(p,new Vector(1,1,1));
    scene.add_object(o);

  }

  void createscene()
  {
    Object o=new Object();
    MyPolygon p;

    Random rnd=new Random();

    int x,y,z,x1,y1,z1;


    int cx[]={2,8};
    int cy[]={0,0};
    int cz[]={3,2};
    int cx1[]={4,4};
    int cy1[]={4,7};
    int cz1[]={2,4};



    Vector cl=new Vector(0.8,0.8,0.8);



    for(int i=0;i<2;i++)
    {
      o=new Object();


     x=cx[i];
     y=cy[i];
     z=cz[i];
     x1=cx1[i];
     y1=cy1[i];
     z1=cz1[i];





    p=new MyPolygon();
    p.addPoint(x,y,z);
    p.addPoint(x,y,z+z1);
    p.addPoint(x,y+y1,z+z1);
    p.addPoint(x,y+y1,z);
    o.add_polygon(p,cl);

    p=new MyPolygon();
    p.addPoint(x+x1,y,z);
    p.addPoint(x+x1,y+y1,z);
    p.addPoint(x+x1,y+y1,z+z1);
    p.addPoint(x+x1,y,z+z1);
    o.add_polygon(p,cl);

    // base of building
    p=new MyPolygon();
    p.addPoint(x,y,z);
    p.addPoint(x+x1,y,z);
    p.addPoint(x+x1,y,z+z1);
    p.addPoint(x,y,z+z1);
    o.add_polygon(p,cl);

    //___Top of building
    p=new MyPolygon();
    p.addPoint(x,y+y1,z);
    p.addPoint(x,y+y1,z+z1);
    p.addPoint(x+x1,y+y1,z+z1);
    p.addPoint(x+x1,y+y1,z);
    o.add_polygon(p,cl);

    //__draw tower
       p=new MyPolygon();
    p.addPoint(x,y+y1,z);
    p.addPoint(x,y+y1,z+z1);
    p.addPoint(x+x1/2,y+y1+y1/3,z+z1/2);
      o.add_polygon(p,cl);


          p=new MyPolygon();
         p.addPoint(x,y+y1,z+z1);
    p.addPoint(x+x1,y+y1,z+z1);
      p.addPoint(x+x1/2,y+y1+y1/3,z+z1/2);
    o.add_polygon(p,cl);


      p=new MyPolygon();
     p.addPoint(x+x1,y+y1,z+z1);
    p.addPoint(x+x1,y+y1,z);
      p.addPoint(x+x1/2,y+y1+y1/3,z+z1/2);
      o.add_polygon(p,cl);

           p=new MyPolygon();
       p.addPoint(x+x1,y+y1,z);
         p.addPoint(x,y+y1,z);
           p.addPoint(x+x1/2,y+y1+y1/3,z+z1/2);
               o.add_polygon(p,cl);


  //___Add more faces
    p=new MyPolygon();
    p.addPoint(x,y,z);
    p.addPoint(x,y+y1,z);
    p.addPoint(x+x1,y+y1,z);
    p.addPoint(x+x1,y,z);
    o.add_polygon(p,cl);

    p=new MyPolygon();
    p.addPoint(x,y,z+z1);
    p.addPoint(x+x1,y,z+z1);
    p.addPoint(x+x1,y+y1,z+z1);
    p.addPoint(x,y+y1,z+z1);
    o.add_polygon(p,cl);

    o.objcenter=new Vector(x+x1/2,y+y1/2,z+z1/2);
    
    scene.add_object(o);


    }

    o=new Object();
//    o.create_sphere(new Vector(8,4,8),3,new Vector(0.4,0.6,0.5));
    o.create_cone(new Vector(10,0,10),3,10,new Vector(0.4,0.1,1));
    o.rotate_z(new Vector(10,0,10),Math.PI/5);
    

    scene.add_object(o);
    //___add lights
    scene.lights[scene.nr_lights++].light=new Light(new Vector(0,300,0),new Vector(0.5,0.7,0.6));
   

    scene.sort( scene.cameraLocation);



  }
  void jbInit() throws Exception
  {
    this.setLayout(borderLayout1);
  }



  
  public void compute()
  {

   //_________Generate transformation matrix
  
      scene.cameraDir= scene.cameraLocation.subtract( scene.cameraLookat);
   //     cameraDir.normalize();

    transform.identity();
    transform.translate(- scene.cameraLocation.get_x(),- scene.cameraLocation.get_y(),- scene.cameraLocation.get_z());

    Matrix m=new Matrix();
    Vector V= scene.cameraDir.add(new Vector(0,10,0));
    m.viewtransform( scene.cameraDir,V);
    transform=m.matrix_multiply(transform);

    double d=  scene.cameraLocation.get_x()* scene.cameraLocation.get_x()+  scene.cameraLocation.get_y()* scene.cameraLocation.get_y()+ scene.cameraLocation.get_z()* scene.cameraLocation.get_z();
    d=Math.sqrt(d);

    m.translate(0,0,d);
    transform=m.matrix_multiply(transform);

    m.perspectiveview( scene.cameraLocation.length());
    transform=m.matrix_multiply(transform);
    

  }
  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);

    int i,j,k;
    Object o;
    MyPolygon p;
    Polygon tp;

    //get translation amount
/*    origin.set(0,0,0);
    origin=transform.vec_postmultiply(origin);
    origin.subtract(new Vector(
  */

    boolean paintflag=true;




     scene.sort( scene.cameraLocation);




          for( i=0; i<scene.nr_lights; i++)
          {
             scene.newlights[i]=new Light(scene.lights[i].light.position,scene.lights[i].light.colour);
             scene.newlights[i].position=scene.lights[i].anim_transform.vec_postmultiply(scene.newlights[i].position);     // apply anim transform
            // System.out.println(scene.newlights[i].position);
            // scene.get_object(i).anim_transform.display();
             
           }


    for(i=0;i<scene.get_nr_objects();i++)
    {
      //System.out.println("Object : " +i);
      //System.out.flush();

      o=scene.get_object(scene.number[i]);

     

      for(j=0;j<o.get_nr_polygons();j++)
      {
        //System.out.println("polygon : " +j);
        //System.out.flush();

        p=o.get_polygon(j);


        //___decide whether to paint polygon or not
           if(p.get_nr_points()>2)
           {
            if( p.get_normal().dot_product( scene.cameraDir)>=-0.0001)

              paintflag=true;
            else
              paintflag=false;
            }
        else
          paintflag=true;

          if(!paintflag)
            continue;


        //____Now draw this polygon after transforming it
        //____and translating the origin


        for(k=0;k<p.get_nr_points();k++)
        {
          Vector point=p.get_point(k);   // point in world cord



            if(action_flag)
              point=o.anim_transform.vec_postmultiply(point);     // apply anim transform

          point=transform.vec_postmultiply(point);   // apply projection


          point=point.divided_by(point.get_h());
          //___get screen coordinates after translating and scaling
          x[k]=(int)origin.get_x()+(int)(point.get_x()*scalefactor);
          y[k]=(int)origin.get_y()-(int)(point.get_y()*scalefactor);
        }




        if( (scene.number[i]==0 && showaxis) || scene.number[i]>0)
        {

        //___determine color for lights
        if(p.get_normal()!=null)
        {
            Vector colour=o.get_colour(j);
            Vector result=scene.lighted_colour(p.return_center(),p.get_normal(), scene.cameraLocation,colour);

            g.setColor(new Color((float)result.get_x(),(float)result.get_y(),(float)result.get_z()));
            if(showwireframe)
              g.drawPolygon(x,y,p.get_nr_points());
            else
              g.fillPolygon(x,y,p.get_nr_points());
          }
          else     //____ this is a line
          {
             g.setColor(o.get_Color(j));
              g.drawPolygon(x,y,p.get_nr_points());
          }

        }
      }
      //transform.display();
    }


    } // end function

}

