/* mekka intro               */
/* c a l o d o x   2 0 0 1   */

#include "main.h"
#include <math.h>
#include "writer.h"
#include "vectors.h"

/*
moveto (P1);                            // move pen to startpoint
for (int t=0; t < steps; t++)
{
  float s = (float)t / (float)steps;    // scale s to go from 0 to 1

  float h1 =  2s^3 - 3s^2 + 1;          // calculate basis function 1
  float h2 = -2s^3 + 3s^2;              // calculate basis function 2
  float h3 =   s^3 - 2*s^2 + s;         // calculate basis function 3
  float h4 =   s^3 -  s^2;              // calculate basis function 4
  vector p = h1*P1 +                    // multiply and sum all funtions
             h2*P2 +                    // together to build the interpolated
             h3*T1 +                    // point along the curve.
             h4*T2;
  lineto (p)                            // draw to calculated point on the curve
}

*/



void SPLINES_generate_points(Vect3D p1, Vect3D p2, Vect3D p3, Vect3D p4, int steps, Vect3D *result)
{
	float st=1.0/steps;
	float h1,h2,h3,h4;
	Vect3D v,t1,t2;
	int j=0;

	t1.x=0.5*(p3.x-p1.x);
	t1.y=0.5*(p3.y-p1.y);
	t1.z=0.5*(p3.z-p1.z);
	
	t2.x=0.5*(p4.x-p2.x);
	t2.y=0.5*(p4.y-p2.y);
	t2.z=0.5*(p4.z-p2.z);

	for (float t=0.0;t<1.0;t+=st)
	{
		h1=2*t*t*t - 3*t*t + 1;
		h2=-2*t*t*t + 3*t*t;
		h3=t*t*t - 2*t*t + t;
		h4=t*t*t - t*t;

		v.x=h1*p2.x + h2*p3.x + h3*t1.x + h4*t2.x;
		v.y=h1*p2.y + h2*p3.y + h3*t1.y + h4*t2.y;
		v.z=h1*p2.z + h2*p3.z + h3*t1.z + h4*t2.z;

		result[j]=v;
		j++;
	}
}








// ^foutre le meme nombre de fonctions pour x et y...

float SPLINES_xfunction(float param, unsigned char which_one, float fctpar1)
{
	if (which_one==0) { return cos(param)*sin(param)*cos(param)*cos(param*fctpar1); }
	if (which_one==1) { return cos(param)*sin(param)*sin(param)*sin(param*fctpar1); }

	return 1.0;
}

float SPLINES_yfunction(float param, unsigned char which_one, float fctpar1)
{
	if (which_one==0) { return sin(param*fctpar1)*sin(param);}
	if (which_one==1) { return cos(param*fctpar1)*sin(param);}

	return 1.0;
}



void SPLINES_Draw_Parametric(float maxt, int nb_pts, int intrasteps, float zoom, float alpha, 
							 Vect2D move, int style_x, int style_y, int blendstyle, float rotat, Vect3D color)
{

	float ts;
	float param[4];
	Vect2D p1,p2,p3,p4;
		Vect2D u1,u2,u3,u4;

	ts=(3.14*2.0*2.0)/nb_pts;


	glDisable(GL_TEXTURE_2D);

		if (blendstyle==1)
		{
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);	// Blending Function For Translucency Based On Source Alpha Value
		}
	
		if (blendstyle==2)
		{
		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
		}

		if (blendstyle==3)
		{
		glBlendFunc(GL_ONE, GL_ZERO);
		}

		if (blendstyle==1 || blendstyle==2 || blendstyle==3)
		{
		glEnable(GL_BLEND);					// Turn Blending On
		}
	
	
		glDisable(GL_DEPTH_TEST);

	for (float t=0.0;t<maxt;t+=ts)
	{

		param[0]=t;
		param[1]=t+ts;
		param[2]=t+ts*2.0;
		param[3]=t+ts*3.0;

		style_x=style_y=0;

		float factor1, factor2;

		if (style_x&32)
		{
		factor1=1.0+fabs(3.0*sin(ACCURATE_TIMER*0.00005));
		factor2=1.0+fabs(6.0*cos(ACCURATE_TIMER*0.00006));
		}
		else
		{
		factor1=3.0;
		factor2=6.0;
		}

		style_x&=31;

		p1.x=SPLINES_xfunction(param[0], style_x, factor1);
		p1.y=SPLINES_yfunction(param[0], style_y, factor2);

		p2.x=SPLINES_xfunction(param[1], style_x, factor1);
		p2.y=SPLINES_yfunction(param[1], style_y, factor2);

		p3.x=SPLINES_xfunction(param[2], style_x, factor1);
		p3.y=SPLINES_yfunction(param[2], style_y, factor2);

		p4.x=SPLINES_xfunction(param[3], style_x, factor1);
		p4.y=SPLINES_yfunction(param[3], style_y, factor2);


		p1.x*=5.0;
		p2.x*=5.0;
		p3.x*=5.0;
		p4.x*=5.0;


		p1=Vect2D_Add(p1, move);
		p2=Vect2D_Add(p2, move);
		p3=Vect2D_Add(p3, move);
		p4=Vect2D_Add(p4, move);


		// calcul des normales a la courbe

		Vect2D p1p2;	Vect2D Np1p2;
		Vect2D p2p3;	Vect2D Np2p3;

		Vect2D z1,z2,z3,z4;

		p1p2=Vect2D_Sub(p2, p1);
		p2p3=Vect2D_Sub(p3, p2);

		p1p2=Vect2D_MulScalar(p1p2, 0.5);
		p2p3=Vect2D_MulScalar(p2p3, 0.5);

		Np1p2=Vect2D_OrthoVector(p1p2);
		Np2p3=Vect2D_OrthoVector(p2p3);

		Np1p2=Vect2D_MulScalar(Np1p2, 0.4);
		Np2p3=Vect2D_MulScalar(Np2p3, 0.4);


		//calcul des coords du polygone

		z1=Vect2D_Add(p1, p1p2);
		z1=Vect2D_Add(z1, Np1p2);

		z2=Vect2D_Add(p1, p1p2);
		z2=Vect2D_Sub(z2, Np1p2);

		z3=Vect2D_Add(p2, p2p3);
		z3=Vect2D_Sub(z3, Np2p3);

		z4=Vect2D_Add(p2, p2p3);
		z4=Vect2D_Add(z4, Np2p3);


		z1=Vect2D_MulScalar(z1, zoom);
		z2=Vect2D_MulScalar(z2, zoom);
		z3=Vect2D_MulScalar(z3, zoom);
		z4=Vect2D_MulScalar(z4, zoom);

	

			glLoadIdentity();										// reset the view
			glTranslatef(0.0f,0.0f,OGL_ZFOV);
			glRotatef(rotat,0.0f, 0.0f,1.0f);



			glBegin(GL_QUADS);
			glColor4f(color.x, color.y, color.z,alpha);
				glVertex3f(z1.x,z1.y, 0.5);	
				glVertex3f(z2.x,z2.y, 0.5);
				glVertex3f(z3.x,z3.y, 0.5);
				glVertex3f(z4.x,z4.y, 0.5);
			glEnd();


	}
		glEnable(GL_DEPTH_TEST);

		if (blendstyle==1 || blendstyle==2 || blendstyle==3)
		{
		glDisable(GL_BLEND);
		}

		glEnable(GL_TEXTURE_2D);
}





void SPLINES_Draw_Text(float maxt, int nb_pts, int intrasteps, float zoom, float alpha, Vect2D move, 
					   unsigned char *strg, int style_x, int style_y, float speed, float factor1, float factor2)
{

	float ts;
	float param[4];
	Vect2D p1,p2,p3,p4;
	int i=0;

	ts=(3.14*2.0*2.0)/nb_pts;


	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
		glEnable(GL_BLEND);					// Turn Blending On
		glDisable(GL_DEPTH_TEST);


	for (float t=0.0;t<maxt;t+=ts)
	{


		if (strg[i]==0) i=0;

		param[0]=t;
		param[1]=t+ts;
		param[2]=t+ts*2.0;
		param[3]=t+ts*3.0;

		param[0]+=speed;
		param[1]+=speed;
		param[2]+=speed;
		param[3]+=speed;

		p1.x=SPLINES_xfunction(param[0], style_x, factor1);
		p1.y=SPLINES_yfunction(param[0], style_y, factor2);

		p2.x=SPLINES_xfunction(param[1], style_x, factor1);
		p2.y=SPLINES_yfunction(param[1], style_y, factor2);

		p3.x=SPLINES_xfunction(param[2], style_x, factor1);
		p3.y=SPLINES_yfunction(param[2], style_y, factor2);

		p4.x=SPLINES_xfunction(param[3], style_x, factor1);
		p4.y=SPLINES_yfunction(param[3], style_y, factor2);


		p1.x*=5.0;
		p2.x*=5.0;
		p3.x*=5.0;
		p4.x*=5.0;

		p1=Vect2D_Add(p1, move);
		p2=Vect2D_Add(p2, move);
		p3=Vect2D_Add(p3, move);
		p4=Vect2D_Add(p4, move);

		// calcul des normales a la courbe

		Vect2D p1p2;	Vect2D Np1p2;
		Vect2D p2p3;	Vect2D Np2p3;

		Vect2D z1,z2,z3,z4;

		p1p2=Vect2D_Sub(p2, p1);
		p2p3=Vect2D_Sub(p3, p2);

		p1p2=Vect2D_MulScalar(p1p2, 1.4);
		p2p3=Vect2D_MulScalar(p2p3, 1.4);

		Np1p2=Vect2D_OrthoVector(p1p2);
		Np2p3=Vect2D_OrthoVector(p2p3);

		Np1p2=Vect2D_MulScalar(Np1p2, 0.4);
		Np2p3=Vect2D_MulScalar(Np2p3, 0.4);


		//calcul des coords du polygone

		z1=Vect2D_Add(p1, p1p2);
		z1=Vect2D_Add(z1, Np1p2);

		z2=Vect2D_Add(p1, p1p2);
		z2=Vect2D_Sub(z2, Np1p2);

		z3=Vect2D_Add(p2, p2p3);
		z3=Vect2D_Sub(z3, Np2p3);

		z4=Vect2D_Add(p2, p2p3);
		z4=Vect2D_Add(z4, Np2p3);


		z1=Vect2D_MulScalar(z1, zoom);
		z2=Vect2D_MulScalar(z2, zoom);
		z3=Vect2D_MulScalar(z3, zoom);
		z4=Vect2D_MulScalar(z4, zoom);

		//on dessine
		
		


			glLoadIdentity();										// reset the view
			glTranslatef(0.0f,0.0f,OGL_ZFOV);

			glRotatef(zoom*32,0.0f, 0.0f,1.0f);

			glColor4f(alpha,alpha,alpha, 1.);	


			float sx= arial_font_normal[strg[i]-32].width/64.0;
			float sy= arial_font_normal[strg[i]-32].height/64.0;

			glBindTexture(GL_TEXTURE_2D,  arial_font_normal[strg[i]-32].glhandle);

			glBegin(GL_QUADS);

				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(z1.x,z1.y, 0.5);	
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(z2.x,z2.y, 0.5);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(z3.x,z3.y, 0.5);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(z4.x,z4.y, 0.5);
			glEnd();


		i++;
	}
		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);
}





