
#include <iostream>
#include <cmath>
using namespace std;

#include <GL/glut.h>


#include <func.h>
#include <func2dovervec3d.h>
#include <gobj.h>
#include <graphmisc.h>
#include <mathlib.h>
#include <meshpatch.h>
#include <meshpatchtest.h>
#include <meshpatchptr.h>
#include <point.h>
#include <pointgrid3D.h>
#include <pointgrid3Ddraw.h>
#include <pointgrid3Dbilineardraw.h>
#include <print.h>
#include <triangleuniformsubdivision.h>
#include <triangles3Tdisplay.h>
#include <triangles3Tdisplaymulticolored.h>
#include <zpr.h>


typedef point3<double> pt3;
typedef point3<double> const pt3c;

class meshtestpatch01
{
public:

  pt3 pi[4];

  pt3c operator () (uintc i, uintc j) const
    { return pi[i+2*j]; }
  pt3 & operator () (uintc i, uintc j) 
    { return pi[i+2*j]; }

  meshtestpatch01();

};

meshtestpatch01::meshtestpatch01()
{
  operator()(0,0) = pt3(0.0,0.0,0.0);
  operator()(1,0) = pt3(1.0,0.0,1.0);
  operator()(1,1) = pt3(1.0,1.0,2.0);
  operator()(0,1) = pt3(0.0,1.0,0.0);
}

void meshpatchtest::test01()
{
  meshpatch m(1,1);

  meshtestpatch01 pij;

  cout << "Enter u v: ";
  double u,v;
  cin >> u >> v;

  pt3 p;
  m.eval(p,u,v,pij);

  cout << SHOW(p) << endl;

}

funcA2(tempsin2,sin((x*x-y*y)*0.25),x,y,double,doublec);
funcA2(tempsin3,sin(x*x-y*y),x,y,double,doublec);
  
gobjContainer xGraphics;

void meshpatchtestdisplay01()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  gobj::global->draw();

  glerrordisplay();
  
  glutSwapBuffers();
}

void meshpatchtestkeyboard01(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
  }
}

void meshpatchtest::test02(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(meshpatchtestdisplay01);
  glutKeyboardFunc(meshpatchtestkeyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);

  zpr zz;

  xGraphics.set();

  //pointgrid3D g(10,10,-1.0,3.0,-1.0,3.0);
  pointgrid3D g(5,4,-1.0,3.0,-1.0,3.0,true);

  pointgrid3Ddraw gd(g);

  gobjpush(&gd);

  tempsin2 f2;

  func2Dovervec3D< point3<double> >(g.pt,g.M*g.N).evalY(f2);

  gd.update();

  //cout << printvecfunc(g.pt,g.M*g.N,"\n") << endl;

  pointgrid3Dbilineardraw gbd(g);
  gobjpush(&gbd);
  gbd.update();  

  
  //gobj::globaldisplaylist();

  zz.update();

  glutMainLoop();
}


void meshpatchtest::test03(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(meshpatchtestdisplay01);
  glutKeyboardFunc(meshpatchtestkeyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);

  zpr zz;


  xGraphics.set();

  vector< point3<double> > pts;
  vector< point3<uint> > vi;

  pts.push_back( point3<double>(0.0,0.0,0.0));
  pts.push_back( point3<double>(1.0,0.0,0.0));
  pts.push_back( point3<double>(0.5,1.0,0.0));

  point3<uint> tri0(0,1,2);
  //vi.push_back(tri0);

/*
  triangleuniformsubdivision< point3<double> > tusd(vi,pts);
  tusd.divide(tri0);
*/

  vector< point3<uint> > vi2;
  triangleuniformsubdivision< point3<double> > tusd2(vi2,pts);

 // tusd2.divide(vi);

 tusd2.divide(tri0,3); 


/*
  vectorprint::space="\n";
  cout << "vi" << endl;
  cout << vi << endl;
  cout << SHOW(vi.size()) << endl;
  cout << "pts" << endl;
  cout << pts << endl;
  cout << SHOW(pts.size()) << endl;
*/

  triangles3Tdisplaymulticolored<GLfloat,double> * td = 
    new triangles3Tdisplaymulticolored<GLfloat,double>(vi2.size(), & vi2[0], & pts[0]);
  gobjpush(td);

  zz.update();
  glutMainLoop();
}


void meshpatchtest::test04(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(meshpatchtestdisplay01);
  glutKeyboardFunc(meshpatchtestkeyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);

  zpr zz;

  xGraphics.set();

  //pointgrid3D g(10,10,-1.0,3.0,-1.0,3.0);
  pointgrid3D g(5,4,-1.0,3.0,-1.0,3.0,true);

  pointgrid3Ddraw gd(g);

  gobjpush(&gd);

  tempsin2 f2;

  func2Dovervec3D< point3<double> >(g.pt,g.M*g.N).evalY(f2);

  gd.update();

  //cout << printvecfunc(g.pt,g.M*g.N,"\n") << endl;

  //pointgrid3Dbilineardraw gbd(g);
  //gobjpush(&gbd);
  //gbd.update();  


  vector< point3<double> > pts;
  vector< point3<uint> > vi;
  g.createIndexedTriangles(pts,vi);

  triangles3Tdisplaymulticolored<GLfloat,double> * td = 
    new triangles3Tdisplaymulticolored<GLfloat,double>(vi.size(), & vi[0], & pts[0]);
  gobjpush(td);
 
  
  zz.update();
  glutMainLoop();
}

  



