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

public class dbuffer 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 du cube d'arête 4.
  // ---------------------------
  l_scene.m_obj = (Objet3D) new Cube(2.0f) ;

  // 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(5,5,5,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(100,100,100,100) ;

  // 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;
   }

  }
