lighting.flx

Animation flash

lighting.flx
/* -*-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;

void label_color(void) { yellow(); }
std::string axis_color="green";

// 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;
    }
  bounding_box(P(-10,-10),P(10,10));
  unitlength("1in");
  picture(4,4);

  use_pstricks();
  begin();
  crop();

  std::cout << "\n\\newrgbcolor{orange}{0.8 0.4 0}";
  use_pstricks(false);

  // black background
  fill();
  gray(1);
  rect(P(-10,-10), P(10,10));
  fill(false);

  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
  label_color();
  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

  use_pstricks();

  // draw grid only
  psset("linecolor=green,linewidth=0.15pt,fillstyle=none");
  plot(F, R);

  // axes (with solid arrowheads) and shaded surface
  psset("fillstyle=solid");
#ifdef AXES
  psset("linewidth=1pt,linecolor="+axis_color+",fillcolor="+axis_color);
  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
  psset("linecolor=orange,linewidth=0.6pt");

  Color chip_color(1,1,1);   // true color of torus
  Color ambient(1,0.75,0);  // ambient light

  Fog fog(Color(1,1,1), 0.0125);

  // spot light location
  P spot_at=sph(10, M_PI_4, 2*M_PI*tix); // traverses a longitude
  // P spot_at=P(5,0,0)+cyl(10, 2*M_PI*tix, 5); // or latitude
  // P spot_at(5,-5,10);                        // or stays put
  Spot spot(Color(0,0,1), 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());

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

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

  if (spot_at.x2() > 0)
    {
      blue();
      box(spot.m_loc);
    }

#ifdef AXES
  // re-draw hidden portions
  psset("linecolor="+axis_color+",linewidth=1pt,fillcolor="+axis_color);
  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

  // redraw front portion of mesh partially covered by solid surface
  psset("linecolor=green,linewidth=0.15pt,fillstyle=none");
  plot(F, R.resize1(0, 0.25*N1));
  use_pstricks(false);


  // labels
  bold();
  white();
  line(P(3,0,6), F(0,0.25*N2));
  line(P(6,0,4), F(0,-0.25*N2));

  black();
  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);

  end();
}