import java.awt.*;
import java.applet.Applet;

public class modelsphere extends Applet
{
  Image           m_im        ;
  Graphics        m_offscreen ;
  CapteurVisuel3D m_obs       ;
  int	            m_prevx     ;

  public void init()
  {
  // création de la scene.
  // ---------------------
  Scene3D l_scene = new Scene3D() ;

  // création d'un objet.
  // -------------------
  String l_pardiam  = getParameter( "DIAMETER" ),
         l_parver   = getParameter( "NB_POINT_PROFIL" ),
         l_parhor   = getParameter( "NB_PROFIL" ),
         l_parangle = getParameter( "ANGLE" ),
         l_parrring = getParameter( "R_RING"),
         l_partype  = getParameter("TYPE" );;
  float  l_diam  = Float.valueOf( l_pardiam  ).floatValue(),
         l_angle = Float.valueOf( l_parangle ).floatValue(),
         l_rring = Float.valueOf( l_parrring ).floatValue();
  int    l_ver = Integer.valueOf( l_parver ).intValue(),
         l_hor = Integer.valueOf( l_parhor ).intValue();

  if ( l_partype.compareTo( "SPHERE" ) == 0 )
     l_scene.m_obj = (Objet3D) new Sphere(l_diam,l_hor, l_ver, l_angle) ;
  if ( l_partype.compareTo( "BOL" ) == 0 )
     l_scene.m_obj = (Objet3D) new Bol(l_diam,l_hor, l_ver, l_angle) ;
  if ( l_partype.compareTo( "CALOTTE" ) == 0 )
     l_scene.m_obj = (Objet3D) new Calotte(l_diam,l_hor, l_ver, l_angle) ;
  if ( l_partype.compareTo( "TORE" ) == 0 )
     l_scene.m_obj = (Objet3D) new Tore(l_diam, l_rring, l_hor, l_ver, l_angle) ;
  if ( l_partype.compareTo( "SURFACE" ) == 0 )
     l_scene.m_obj = (Objet3D) new Surface(l_diam, l_hor, l_ver, l_angle) ;


  // création du capteur.
  // ---------------------
  // rappel: le fait de référencer la scène dans le capteur garde cette dernière
  // en mémoire aprés la sortie du bloc quand la référence l_scene est detruite.
  m_obs = new CapteurVisuel3D( l_scene ) ;

  // ici la gestion de la mémoire de Java nous aide. En effet, il est desormais
  // inutile de désallouer les sommets m_a et m_b. une seule affectation d'une
  // nouvelle référence suffit.
  m_obs.m_direction.m_a = new Sommet3DH(8,8,8,1);
  m_obs.m_direction.m_b = new Sommet3DH(0,0,0,1);

  m_obs.m_ouverture  = 15  ;
  m_obs.m_profondeur = 400 ;
  m_obs.m_spin       = 0   ;

  m_obs.m_fenetre = new Fenetre3D(size().width/2,size().height/2,
                                  size().width/2,size().height/2) ;

  // on initialise la matrice de transformation
  m_obs.CalculPerspective() ;

  // on rattache le capteur à la scène.
  l_scene.m_obs = m_obs ;

  try
   {
   m_im = createImage(size().width, size().height); // création d’unobjet image.
   m_offscreen = m_im.getGraphics(); // création d’un objet Graphics
   }
  catch (Exception e)
   {
   // Une erreur c’est produite l’ors de l’allocation des objets.
   // Cela implique que la technique du double buffer n’est pas utilisable.
   // Le programme peut toutefois continuer.
   m_offscreen = null;
   }
  }

  public void paintApplet(Graphics p_g)
   {
   // dessin filaire de la scene.
   m_obs.VisualisationFilaireScene(p_g);
   p_g.drawString( "(c) Virtual Design 1996",10,size().height-20) ;
   }

  public void update(Graphics p_g)
   {
   paint(p_g);
   }

  public void paint(Graphics p_g)
   {
   if (m_offscreen != null)
    {
    //  le cas ou la technique du double buffer est utilisable
    m_offscreen.setColor(Color.lightGray);
    m_offscreen.fillRect(0,0,size().width, size().height);
    m_offscreen.setColor(Color.blue);
    paintApplet(m_offscreen);
    p_g.drawImage(m_im, 0, 0,this);
    }
   else
    {
    //  pas de technique de double buffer.
    paintApplet(p_g);
    }
   }

   public void destroy()
    {
    if (m_offscreen != null)
     {
     m_offscreen.dispose();
     }
    }

  public boolean mouseDown(Event e, int x, int y)
   {
	m_prevx = x;
	return true;
   }

  public boolean mouseDrag(Event e, int x, int y)
   {
	Matrice44 l_mat = new Matrice44();
	float l_theta = (float)((x - m_prevx) * Math.PI / size().width);
   float l_cos = (float)Math.cos(l_theta) ,
         l_sin = (float)Math.sin(l_theta) ;

	l_mat.setRotateZ(l_cos,l_sin);

   m_obs.m_direction.m_a.multiplyByMatrix(l_mat);
   m_obs.CalculPerspective() ;

	repaint();

	m_prevx = x;

	return true;
   }

  }