/*********************************************************************************************/
/*                                                                                           */
/*  Java 3D Simple - 3D Wire Cube (with mouse input)                                         */
/*  Auth: bkenwright@xbdev.net                                                               */
/*  URL: www.xbdev.net                                                                       */
/*                                                                                           */
/*  Creating a simple wireframe 3D demo                                                      */
/*  It looks like a lot...but its mostly comments believe me.  The only code in 3D here      */
/*  that may be a bit tricky to understand...well thats if your not from a 3D background     */
/*  is the rotation equations...everything else is pretty much simple...just a matter of     */
/*  arranging the data into nice tidy parts.  For example, we have 8 corners of a cube...and */
/*  those 8 corners are used to create 12 lines which make up the wire cube!..ta-daaAA.      */
/*  And thats it :)                                                                          */
/*  We use a bit of mouse input and of course...the rotation equations and translation etc   */
/*  so it looks better.                                                                      */
/*  Just drag the mouse and watch it move around...coOOoool.                                 */
/*                                                                                           */
/*********************************************************************************************/

import java.awt.image.*;
import java.awt.*;
import java.applet.*;

/*********************************************************************************************/
class Point3 
{
   public float x, y, z;
   public Point3( int xx, int yy, int zz ) 
	 {
      x = xx;  y = yy;  z = zz;
   }// End constructor
}// End Point3 class

/*********************************************************************************************/

class Line 
{
   public int p0, p1;
   public Line( int a, int b ) 
	 {
      p0 = a;  p1 = b;
   }// End constructor
}// End class Edge


/*********************************************************************************************/
/*                                                                                           */
/* Program Entry Point!                                                                      */
/* Let the coding begin....                                                                  */
/*                                                                                           */
/*********************************************************************************************/

public class wire_cube extends Applet
{

   Point3[] vertices;
   Line[]   lines;
   
   int scr_width;
   int scr_height;
   
   // We'll only rotate around the x and y for simplicity :)
   float angle_y = 1.0f;
   float angle_x = 1.0f;
   
   // Mouse coords
   int mx;
   int my;
   int mb;

   public void init() 
	 {
      scr_width  = getSize().width;
      scr_height = getSize().height;

      vertices = new Point3[ 8 ];
      vertices[0] = new Point3( -1, -1, -1 );
      vertices[1] = new Point3( -1, -1,  1 );
      vertices[2] = new Point3( -1,  1, -1 );
      vertices[3] = new Point3( -1,  1,  1 );
      vertices[4] = new Point3(  1, -1, -1 );
      vertices[5] = new Point3(  1, -1,  1 );
      vertices[6] = new Point3(  1,  1, -1 );
      vertices[7] = new Point3(  1,  1,  1 );

      lines = new Line[ 12 ];
      lines[ 0] = new Line( 0, 1 );
      lines[ 1] = new Line( 0, 2 );
      lines[ 2] = new Line( 0, 4 );
      lines[ 3] = new Line( 1, 3 );
      lines[ 4] = new Line( 1, 5 );
      lines[ 5] = new Line( 2, 3 );
      lines[ 6] = new Line( 2, 6 );
      lines[ 7] = new Line( 3, 7 );
      lines[ 8] = new Line( 4, 5 );
      lines[ 9] = new Line( 4, 6 );
      lines[10] = new Line( 5, 7 );
      lines[11] = new Line( 6, 7 );

      //backbuffer = createImage( width, height );
      //backg = backbuffer.getGraphics();
      //drawWireframe( backg );
      repaint();
   }// End init(..)

   
	 void renderWireCube( Graphics g ) 
	 {
      float cosY = (float)Math.cos(angle_y);
      float sinY = (float)Math.sin(angle_y);
      
      float cosX = (float)Math.cos(angle_x);
      float sinX = (float)Math.sin(angle_x);
      
      Point[] points = new Point[8];
      
      // Transformed start and end point
      Point3 tpA = new Point3(0,0,0);
      Point3 tp  = new Point3(0,0,0);
      // Lets loop through all the lines and transform them
      for(int i=0; i<8; i++)
      {
        Point3 p = vertices[i];
        
        //Rotate around the X axis
        tp.x   =  p.x;
        tp.y   =  cosX*p.y - sinX*p.z;
        tp.z   =  sinX*p.y + cosX*p.z;
        
        //Rotate around the Y axis
        tpA.x   =  cosY*tp.x + sinY*tp.z;
        tpA.y   =  tp.y;
        tpA.z   = -sinY*tp.x + cosY*tp.z;
        
        
        // Translate (e.g move) our Cube away from us (into the z background)
        tpA.z += 3;
        
        float scr_x = tpA.x / tpA.z;
        float scr_y = tpA.y / tpA.z;
        
        scr_x += 1;           scr_y += 1;
        scr_x *=0.5f;         scr_y *= 0.5f;
        scr_x *= scr_width;   scr_y *= scr_height;
        
        points[i] = new Point( (int)scr_x, (int)scr_y );
      }// End for loop i
      
      // Clear the screen
      g.setColor( Color.black );
      g.fillRect( 0, 0, scr_width, scr_height );
      
      for(int j=0; j<12; j++)
      {
         int p0 = lines[j].p0;
         int p1 = lines[j].p1;
         g.setColor( Color.white );
         g.drawLine( points[p0].x, points[p0].y,  points[p1].x, points[p1].y );
      }// End for loop j
      
   }// End renderWireCube(..)
   
      
   public void update( Graphics g ) 
	 {
	    renderWireCube( g );
      showStatus("y angle " + (angle_y * (180.0f/3.14f))%180 );
   }// End update(..)

   public void paint( Graphics g ) 
	 {
      update( g );
   }// End paint(..)


/*********************************************************************************************/
/*                                                                                           */
/*  Capture event when mouse is pressed                                                      */
/*    Parameters:                                                                            */
/*    evt is The event...                                                                    */
/*    x is the x mouse position                                                              */
/*    y is the y mouse position                                                              */
/*    return whether or not we handled the event                                             */
/*                                                                                           */
/*********************************************************************************************/

	public boolean mouseDown(Event evt, int x, int y)
  {
     mb = 1;
		 return true;
	}// End of mouseDown(..)

/*********************************************************************************************/
/*                                                                                           */
/*  Capture mouse release                                                                    */
/*    Parameters:                                                                            */
/*    evt is The event...                                                                    */
/*    x is the x mouse position                                                              */
/*    y is the y mouse position                                                              */
/*    return whether or not we handled the event                                             */
/*                                                                                           */
/*********************************************************************************************/

	public boolean mouseUp(Event evt, int x, int y)
	{
	  mb=0;
		return false;
	}// End of mouseUp(..)
	

/*********************************************************************************************/
/*                                                                                           */
/* Captures mouse movement                                                                   */
/* -> Was added so that the dagging of the wire cube was more smooth...as if you click at a  */
/* new place on the screen, there would be a sudden jump...this way its smooth right from    */
/* your first click with the mouse :)                                                        */
/*                                                                                           */
/*********************************************************************************************/

  public boolean mouseMove(Event evt, int x, int y)
  {
    // Update our old mouse pos
	  mx = x;
	  my = y;
    return true;
  }// End mouseMove(..)

/*********************************************************************************************/
/*                                                                                           */
/*  Capture mouse drags                                                                      */
/*    Parameters:                                                                            */
/*    evt is The event...                                                                    */
/*    x is the x mouse position                                                              */
/*    y is the y mouse position                                                              */
/*    return whether or not we handled the event                                             */
/*                                                                                           */
/*********************************************************************************************/

	public boolean mouseDrag(Event evt, int x, int y)
	{
	  if( mb == 1 )
	  {
	     int xnew = my - y;
	     int ynew = mx - x;
	     
	     angle_y += ynew*0.05f;
	     angle_x += xnew*0.05f;
	     
	     // Update the screen
	     repaint();
	  }// End if(..)
	  
	  // Update our old mouse pos
	  mx = x;
	  my = y;
	     
  	return true;
	}// End of mouseDrag(..)

	
}// End of Applet


