/* -*-flix-*- */
// compile with flix -I. [-DAXES] lighting.flx
// in a directory containing lighting.h
#include "epix.h"
#include "lighting.h"
using namespace ePiX;

// mesh intervals for torus
int N1(36), N2(12);

// torus
P F(double x, double y)
{
  double R(5-2*Sin(M_PI*y/N2));
  return P(R*Cos(2*M_PI*x/N1), R*Sin(2*M_PI*x/N1), 2*Cos(M_PI*y/N2));
}

int main(int argc, char* argv[])
{
  if (argc == 3)
    {
      char* arg;
      double temp1, temp2;
      temp1=strtod(argv[1], &arg);
      temp2=strtod(argv[2], &arg);

      tix()=temp1/temp2;
    }
  picture(P(-10,-10),P(10,10), "4x4in");

  begin();
  set_crop();

  backing(Black());

  domain R(P(0,N2), P(N1,2*N2), mesh(N1,N2), mesh(2*N1,2*N2));

  // manual layering below may require adjustment if the camera is moved
  camera.at(P(4,6,4));
  camera.range(16);

#ifdef AXES
  yellow();
  label(P(8,0,0), P(-2,-2), "$\\mathbf{x}$", bl);
  label(P(0,8,0), P( 2,-2), "$\\mathbf{y}$", br);
  label(P(0,0,8), P( 0, 4), "$\\mathbf{z}$", t);
#endif

  // draw grid only
  pen(Green(), 0.15);
  plot(F, R);

  // axes (with solid arrowheads) and shaded surface
#ifdef AXES
  arrow(P(0,0,0), P(8,0,0));
  arrow(P(0,0,0), P(0,8,0));
  arrow(P(0,0,0), P(0,0,8));
#endif

  rgb(0.8, 0.4, 0);
  fill();
  Color chip_color(White());     // true color of torus
  Color ambient(RGB(1,0.75,0));  // ambient light

  Fog fog(White(), 0.0125);

  // spot light location
  P spot_at(sph(10, M_PI_4, 2*M_PI*tix())); // traverses a longitude

  // P spot_b=P(5,0,0)+cyl(10, 2*M_PI*tix(), 5); // or latitude
  // P spot_b(5,-5,10);                        // or stays put
  Spot spot(Blue(), spot_at);

  std::vector<Chip> surf_mesh;
  // torus, surface reflectivity .75
  for (int i=0; i<N1; ++i)
    for (int j=0; j<N2; ++j)
      surf_mesh.push_back(Chip(F(i,j), F(i+1,j), F(i+1,j+1), F(i,j+1),
			       0.75, chip_color));

  sort(surf_mesh.begin(), surf_mesh.end(), chip_distance());

#ifdef SHOW_SPOT
  // mark spot light's location
  if (spot_at.x2() <= 0)
    {
      blue();
      box(spot.m_loc);
    }
#endif

  // draw shaded surface mesh
  for (unsigned int i=0; i<surf_mesh.size(); ++i)
    surf_mesh.at(i).draw(fog, spot, ambient);

#ifdef SHOW_SPOT
  if (spot_at.x2() > 0)
    {
      blue();
      box(spot.m_loc);
    }
#endif

#ifdef AXES
  // re-draw hidden portions
  green();
  line(P(3,0,0), P(8,0,0));
  line(P(0,3,0), P(0,8,0));
  line(P(0,0,0), P(0,0,8));
#endif

  fill(false);
  // redraw front portion of mesh partially covered by solid surface
  pen(Green(), 0.15);
  plot(F, R.resize1(0, 0.25*N1));

  // labels
  base(White(), 1);
  line(P(3,0,6), F(0,0.25*N2));
  line(P(6,0,4), F(0,-0.25*N2));

  label_border(Green(0.6), "0.5pt");
  label_color(Black());
  label_mask(RGB(1,0.8,0.2));

  font_size("footnotesize");
  masklabel(P(3,0,6), P(0,0), "Total curvature $-\\pi$", t);
  masklabel(P(6,0,4), P(0,0), "Total curvature $\\pi$", t);

  pst_format();
  end();
}
