/* Static Slide Code Generator: Wave
 * Author: James Liao
 */

import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.rmi.*;
import java.util.LinkedList;
import java.util.Random;

public class wave {
  static int sideLength = 0;
  static final double MYDETAIL = 2;

  //takes 1 argument, the dimensions of the box
  static void main(String[] args) {
    sideLength = Integer.parseInt(args[0]);

    double[][] thePoints = new double[sideLength][sideLength];

    for(int yindex = 0; yindex < sideLength; yindex++) {
      for(int xindex = 0; xindex < sideLength; xindex++) {
	thePoints[xindex][yindex] = theFunction(xindex, yindex, sideLength/2, sideLength/2);
//	thePoints[xindex][yindex] += theFunction(xindex, yindex, sideLength/3, sideLength/2);
	System.out.print("\npoint p" + xindex + "_" + yindex);
	//System.out.print(" ( { expr " + xindex + "/ $supersimple_detail } " + "{ expr " + yindex + "/ $supersimple_detail }" + thePoints[xindex][yindex] + ")");
	System.out.print(" ( " + ((double)xindex/MYDETAIL) + " " + ((double)yindex/MYDETAIL) + " " + thePoints[xindex][yindex] + ")");
	System.out.print(" endpoint");
      }
    }

	bsplinepatches();


    System.out.print("\ngroup World");
    System.out.print("  instance theWave");
    System.out.print("  translate (" + (-1 * sideLength / (2 * MYDETAIL)) + " " + (-1 * sideLength / (2*MYDETAIL)) + " " + "0)");
    System.out.print("  endinstance");
    System.out.print("\nendgroup");




	System.out.print("\n############################################################################");
	System.out.print("\n# 3) Add Color");
	System.out.print("\n#");
	System.out.print("\n#    In the Barbell group we specified the surface color of each instance.");
	System.out.print("\n#    Now we need to define these surfaces.");

	System.out.print("\nsurface sBlue");
	System.out.print("\n  color (0.0 0.0 1.0)");
	System.out.print("\nendsurface");

	System.out.print("\nsurface sRed");
	System.out.print("\n  color (1.0 0.0 0.0)");
	System.out.print("\nendsurface");


	System.out.print("\n############################################################################");
	System.out.print("\n# 4) Create Sliders with Tcl/Tk");
	System.out.print("\n#");
	System.out.print("\n#  The following Tcl/Tk code shows how to create the sliders and variables");
	System.out.print("\n#  that we referenced above.");


	System.out.print("\n#  Make a Tcl initialization block");

	System.out.print("\ntclinit {");
	System.out.print("\n  set winName .slfWINDOW");

	System.out.print("\n  ### include some tcl libraries");
	System.out.print("\n  source SLIDEUI.tcl");
	System.out.print("\n  source MATH.tcl");


System.out.print("\n  ### This defines a procedure called CreateSliders");
System.out.print("\n  proc CreateSliders { parent name } {");

System.out.print("\n    ### Don't worry about this stuff ...");
System.out.print("\n    set subname \"slf_[subst $name]\"");

System.out.print("\n    if { $parent == {} } {");
System.out.print("\n	set root .$subname");
System.out.print("\n    } elseif { $parent == \".\" } {");
System.out.print("\n	set root .$subname");
System.out.print("\n    } else {");
System.out.print("\n	set root $parent.$subname");
System.out.print("\n    }");

System.out.print("\n    toplevel $root");


System.out.print("\n    ### This is where the sliders are actually created ! ! !");

System.out.print("\n    ### variable name       variable name    slider text");
System.out.print("\n    ###  |                             |     |");
System.out.print("\n    ###  V                             V     V       ");

System.out.print("\n    set detail [CreateScale $name $root detail \"slices\" 3 1 20 1 1 horizontal]");
//System.out.print("\n    set detail2 [CreateScale $name $root detail2 \"closeness of points\" 3 1 20 1 1 horizontal]");

System.out.print("\n    ###                                            ^  ^   ^  ^");
System.out.print("\n    ###                                            |  |   |  |");
System.out.print("\n    ###                     initial slider value---'  |   |  |");
System.out.print("\n    ###                     minimum slider value------'   |  |");
System.out.print("\n    ###                     maximum slider value----------'  `- slider step value");



System.out.print("\n    ### This line is important too.  This tells the window to display the sliders.");

//System.out.print("\n    pack $detail1 $detail2  -side top -fill x");
System.out.print("\n    pack $detail -side top -fill x");
System.out.print("\n  }");

System.out.print("\n  ### This calls the procedure that creates the sliders");
System.out.print("\n  CreateSliders $winName supersimple");
System.out.print("\n}");


System.out.print("\n########################################################################################");
System.out.print("\n# The code below this line specifies the camera, lighting, and rendering.");
System.out.print("\n# Don't worry too much about this for now.");


System.out.print("\n#################### ");
System.out.print("\n# CAMERA");
System.out.print("\n#################### ");

System.out.print("\ncamera cam");
System.out.print("\n  projection SLF_PARALLEL");
System.out.print("\n  frustum ( -10 -10 -100 ) ( 10 10 100 )");
System.out.print("\nendcamera");

System.out.print("\ngroup gCamera");
System.out.print("\n  instance cam");
System.out.print("\n    id instCam");
System.out.print("\n    translate ( 0.0 0.0 1.0 )");
System.out.print("\n  endinstance");
System.out.print("\nendgroup");

System.out.print("\n#################### ");
System.out.print("\n# LIGHTS");
System.out.print("\n#################### ");

System.out.print("\nlight lite");
System.out.print("\n  type SLF_DIRECTIONAL");
System.out.print("\nendlight");

System.out.print("\ngroup gLight");
System.out.print("\n  instance lite");
System.out.print("\n    id instLite");
System.out.print("\n    lookat");
System.out.print("\n      eye ( 1.0 1.0 1.0 )");
System.out.print("\n      target ( 0.0 0.0 0.0 )");
System.out.print("\n      up ( 0.0 1.0 0.0 )");
System.out.print("\n    endlookat");
System.out.print("\n  endinstance");
System.out.print("\nendgroup");

System.out.print("\nlight lite2");
System.out.print("\n  type SLF_AMBIENT");
System.out.print("\n  color (0.5 0.5 0.5)");
System.out.print("\nendlight");

System.out.print("\ngroup gLight2");
System.out.print("\n  instance lite2");
System.out.print("\n    id instLite2");
System.out.print("\n  endinstance");
System.out.print("\nendgroup");

System.out.print("\n####################");
System.out.print("\n# RENDER");
System.out.print("\n####################");

System.out.print("\nwindow WINDOW");
System.out.print("\nendwindow");

System.out.print("\nviewport VIEWPORT WINDOW");
System.out.print("\n  origin ( 0.0 0.0 )");
System.out.print("\n  size ( 1.0 1.0 )");
System.out.print("\nendviewport");

System.out.print("\nrender VIEWPORT gCamera.instCam.cam World");
System.out.print("\n  light gLight.instLite.lite");
System.out.print("\n  light gLight2.instLite2.lite2");
System.out.print("\nendrender");




  }

static void bsplinepatches() {
	    int numberOfXPatches = sideLength - 3;
	    int numberOfYPatches = sideLength - 3;

	    for(int ypatchIndex = 0; ypatchIndex < numberOfYPatches; ypatchIndex++) {
	      for(int xpatchIndex = 0; xpatchIndex < numberOfXPatches; xpatchIndex++) {

		System.out.println("\nbsplinepatch thePool" + xpatchIndex + "_" + ypatchIndex);
		System.out.println("uslices { expr $supersimple_detail }");
		System.out.println("vslices { expr $supersimple_detail }");
		System.out.println("controlpointlist (");

		for(int yindex = ypatchIndex; yindex < 4 + ypatchIndex; yindex++) {
		  for(int xindex = xpatchIndex; xindex < 4 + xpatchIndex; xindex++) {
		    System.out.print("p" + xindex + "_" + yindex + " ");
		  }
		  System.out.print("\n");
		}

		System.out.println(")");
		System.out.println("endbsplinepatch");
	      }
	    }


	    System.out.println("\ngroup theWave");

	    for(int ypatchIndex = 0; ypatchIndex < numberOfYPatches; ypatchIndex++) {
	      for(int xpatchIndex = 0; xpatchIndex < numberOfXPatches; xpatchIndex++) {
		System.out.print("\ninstance thePool" + xpatchIndex + "_" + ypatchIndex);
		System.out.print("  surface sRed");
		System.out.print("  endinstance");
	      }
	    }
	System.out.println("\n endgroup");
  }


  static double theFunction(double x, double y, double mydropX, double mydropY) {
    double distanceFromDrop = Math.pow(Math.abs(mydropX - x), 2) + Math.pow(Math.abs(mydropY - y), 2);
    distanceFromDrop = Math.sqrt(distanceFromDrop);
    if(distanceFromDrop == 0)
      return 0;
    else
      return 20 * Math.sin(distanceFromDrop) / distanceFromDrop;
  }

  static double theFunction3(int x, int y) {
	return Math.pow(Math.sin(x), 2) + Math.pow(y, 2)/4;
  }

  static double theFunction2(int x, int y) {
	  if(x == 0 || y == 0)
	  	return 0;
	  else
	return (Math.sin(x) * Math.sin(y)) / (x * y);
}
}


