
#include <unistd.h>
#include <sys/wait.h>

#include "ply.h"

#include "Common.h"
#include "ScratchPad.h"
#include "Surface.h"
#include "PerceivedLuminance.h"
#include "plydecl.h"


float decimation_constant_s = 10.0;
float decimation_constant_e = 1.0;


DiffuseDecimatedSurface* ScratchPad::constructDiffuseDecimatedSurface(const float threshold)
{
  int                      fdpRpkToPly[2];
  int                      fdpPlyToRpk[2];
  int                      pid;
  DiffuseDecimatedSurface* dds = NULL;

  // Add accumulation parameter
  addAccum();

  // Prepare the fork
  pipe(fdpRpkToPly);
  pipe(fdpPlyToRpk);
  pid = fork();
  switch (pid)
    {
    case -1:
      fprintf(stderr,"Fork failed\n");
      break;

    case 0:
      // Child

      // Standard input <== reading side of Father->Child pipe.
      close(fdpRpkToPly[1]);
      close(0);
      dup(fdpRpkToPly[0]);

      // Standard output <== writing side of Child->Father pipe.
      close(fdpPlyToRpk[0]);
      close(1);
      dup(fdpPlyToRpk[1]);
      
      // Pipe into it
      close(fdpRpkToPly[0]);
      close(fdpPlyToRpk[1]);

      //      chdir("../SE");
      execlp("desimplify",NULL);
      exit(0);
      break;

    default:
      {
	//	FILE *fich;
	PlyFile *ply;

	// Parent
	close(fdpRpkToPly[0]);
	close(fdpPlyToRpk[1]);
      
	// Other files are closed by following lines...
	writePlyFile(fdpRpkToPly[1],threshold);
	dds = new DiffuseDecimatedSurface(patch,fdpPlyToRpk[0],ply);
	while (wait(NULL)!=pid) ;
	//ply_close(ply);
	close(fdpPlyToRpk[0]);
      }
      return dds;
    }

  return NULL;
}


void ScratchPad::writePlyFile(int fd,const float threshold)
{
  FILE             *fich;
  PlyFile          *ply;
  DecimationVertex dv;
  DecimationFace   df;
  int              i,j,k,kp;
  float            delta,s,it;
  //VEC2D            vv,vw,pos;
  RGB              rgb;

  if (threshold<=0.0)
    it = 1000000.0;
  else
    it = 1.0f/threshold;

  // Open stream
  fich = fdopen(fd,"w");

  // Open ply file from stream
  ply = ply_write(fich,decimation_num_elems,decimation_elem_names,decimation_file_type);


  // Write header
  
  // Describe vertex element
  ply_describe_element(ply,
		       decimation_elem_names[0],
		       curnumcoef,
		       8,
		       decimation_vert_props);

  // Describe face element
  ply_describe_element(ply,
		       decimation_elem_names[1],
		       issquare ? curnumsub*curnumsub*2 : curnumsub*curnumsub,
		       1,
		       decimation_face_props);


  // Finish header
  ply_header_complete(ply);


  // Prepare to write vertex
  ply_put_element_setup(ply,decimation_elem_names[0]);

  // Delta
  delta = 1.0f / curnumsubfp;
  s = decimation_constant_s*curnumsubfp; // * decimation_constant_e / hmin;

  if (issquare)
    {
      dv.v = 0.0;
      k = 0;
      for (j=0;j<curnumline;j++)
	{
	  dv.u = 0.0;
	  
	  //VEC2DSCALE(dv.v,cv,vv);
	  //VEC2DSCALE(dv.v,cw,vw);
	  //VEC2DADD(vw,cu,vw);

	  for (i=0;i<curnumline;i++)
	    {
	      //VEC2DADDSCALED(vv,dv.u,vw,pos);
	      dv.x = dv.u*s;
	      dv.y = dv.v*s;

	      dv.z = perceivedLuminance(elems[k].rad)*it;

	      ColorToRGB(elems[k].rad, &rgb);
	      dv.r = rgb.r;
	      dv.g = rgb.g;
	      dv.b = rgb.b;
	      
	      ply_put_element(ply,(void*)&dv);

	      dv.u += delta;
	      k++;
	    }
	  dv.v += delta;
	}

      ply_put_element_setup(ply,decimation_elem_names[1]);
      df.nverts = 3;
      df.verts = new int[3];

      k = 0;
      for (j=0;j<curnumsub;j++)
	{
	  for (i=0;i<curnumsub;i++)
	    {
	      df.verts[0] = k;
	      df.verts[1] = k+curnumline+1;
	      df.verts[2] = k+curnumline;
	      ply_put_element(ply,(void*)&df);
	      
	      df.verts[0] = k;
	      df.verts[1] = k+1;
	      df.verts[2] = k+curnumline+1;
	      ply_put_element(ply,(void*)&df);

	      k++;
	    }
	  k++;
	}
      
      delete df.verts;
    }
  else
    {
      dv.u = 1.0;
      k = 0;
      for (j=0;j<curnumline;j++)
	{
	  dv.v = 0.0;
	  
	  //VEC2DSCALE(dv.u,cu,vv);

	  kp = k;
	  for (i=0;i<=j;i++)
	    {
	      //VEC2DADDSCALED(vv,dv.v,cv,pos);
	      dv.x = dv.u*s;
	      dv.y = dv.v*s;
	      
	      dv.z = perceivedLuminance(elems[kp].rad)*it;

	      ColorToRGB(elems[kp].rad, &rgb);
	      dv.r = rgb.r;
	      dv.g = rgb.g;
	      dv.b = rgb.b;
	      
	      ply_put_element(ply,(void*)&dv);

	      dv.v += delta;
	      kp++;
	    }
	  k += curnumline;
	  dv.u -= delta;
	}

      ply_put_element_setup(ply,decimation_elem_names[1]);
      df.nverts = 3;
      df.verts = new int[3];

      k = 0;
      for (j=0;j<curnumsub;j++)
	{
	  kp = k;
	  for (i=0;i<=j;i++)
	    {
	      df.verts[0] = kp;
	      df.verts[1] = kp+j+2;
	      df.verts[2] = kp+j+1;
	      ply_put_element(ply,(void*)&df);
	      
	      if (i!=j)
		{
		  df.verts[0] = kp;
		  df.verts[1] = kp+1;
		  df.verts[2] = kp+j+2;
		  ply_put_element(ply,(void*)&df);
		}

	      kp++;
	    }
	  k += j+1;
	}
      
      delete df.verts;
    }

  ply_close(ply);
}














