//Antidem N192, p.192
//#include "stdafx.h"
#include<windows.h>
#include"gl/freeglut.h"
#include <math.h>
#define PI       3.14159265358979323846
#define N 20
float Trot = 0;
float Qrot = 0;
void  display(void);
void KeyDown(unsigned char key, int x, int y);
void SpecKeyDown(int key, int x, int y);
void mousefunction(int button, int state, int x, int y);
void MouseMotion(int x, int y);

//int alpha=300;
int rotate1 = 0, rotate = 0;
double spin = 0.0;
double alfa = 10,//15,
beta = 30;//30;
int ox = 0, oy = 0;
float matrix[16];

int time = 0;
//a^2>b^2 - пузатий
//a^2<b^2 - худий
const double a = 0.3;
const double b = 0.6;
const double c = 0.9;
double u;//[-pi/2,pi/2]
double v;//[0,2pi]
void  myReshape(GLsizei w, GLsizei h)
{
	glMatrixMode(GL_PROJECTION); /* prepare for and then */
	glLoadIdentity(); /* define the projection */
	//glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);/* transformation */
	glOrtho(-250, 250, -250, 250, -250, 250);

	glMatrixMode(GL_MODELVIEW); /* back to modelview matrix */
	glViewport(0, 0, w, h); /* define the viewport */
}


int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	//AUX_DOUBLE | AUX_RGBA | AUX_DEPTH | AUX_STENCIL. 
//: AUX_INDEX | AUX_SINGLE 

	glutInitWindowSize(500, 500);
	glutInitWindowPosition(0, 0);

	glutCreateWindow("3D");

	glutReshapeFunc(myReshape);

	glutKeyboardFunc(KeyDown);
	glutSpecialFunc(SpecKeyDown);

	glutMouseFunc(mousefunction);
	glutMotionFunc(MouseMotion);

	//glutIdleFunc(display);
	glShadeModel(GL_FLAT);//GL_FLAT
	glutDisplayFunc(display);
	glutMainLoop();
	return 0;
}

void display(void) //CALLBACK or WINAPI
{
	double h1 = PI / N;
	double h2 = PI / N * 2.0;
	double R = 100, r = 40;

	glClear(GL_COLOR_BUFFER_BIT);
	glPushMatrix();
	glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
	//glTranslated(100,100,0);
	glRotated(time / 10, 1, 1, 1);
	glColor3ub(255, 255, 255);
	glBegin(GL_LINES); //
	glVertex3f(0, 0, 0);
	glVertex3f(100, 0, 0);
	glVertex3f(0, 0, 0);
	glVertex3f(0, 100, 0);
	glVertex3f(0, 0, 0);
	glVertex3f(0, 0, 100);
	glEnd();
	//glPointSize(10);


	for (int i = 0; i <= 2 * N; i++)
	{
		glBegin(GL_LINE_STRIP);
		//glBegin(GL_POINTS);
		for (int j = 0; j <= N; j++)
		{
			//double x=a*cos((i-N/2)*h1)*cos(PI+(j-N/2)*h2)+b*sin((i-N/2)*h1)*sin(PI+(j-N/2)*h2);
			//double y=a*cos((i-N/2)*h1)*sin(PI+(j-N/2)*h2)-b*sin((i-N/2)*h1)*cos(PI+(j-N/2)*h2);
			//double z=c*sin((i-N/2)*h1);

			double x = (R + r * cos((j - N / 2) * h2)) * cos((i - N / 2) * h1);
			double y = (R + r * cos((j - N / 2) * h2)) * sin((i - N / 2) * h1);
			double z = r * sin((j - N / 2) * h2);

			glVertex3d(x, y, z);
		}
		glEnd();
	}
	for (int j = 0; j <= N; j++)
	{
		glBegin(GL_LINE_STRIP);
		//glBegin(GL_POINTS);
		for (int i = 0; i <= 2 * N; i++)
		{
			//double x=a*cos((i-N/2)*h1)*cos(PI+(j-N/2)*h2)+b*sin((i-N/2)*h1)*sin(PI+(j-N/2)*h2);
			//double y=a*cos((i-N/2)*h1)*sin(PI+(j-N/2)*h2)-b*sin((i-N/2)*h1)*cos(PI+(j-N/2)*h2);
			//double z=c*sin((i-N/2)*h1);

			double x = (R + r * cos((j - N / 2) * h2)) * cos((i - N / 2) * h1);
			double y = (R + r * cos((j - N / 2) * h2)) * sin((i - N / 2) * h1);
			double z = r * sin((j - N / 2) * h2);

			glVertex3d(x, y, z);
		}

		glEnd();
	}
/*
	glColor3ub(255, 0, 0);
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < 2 * N; i++)
	{
		double x = (R + r * cos(3 * (i - N / 2) * h1)) * cos(2 * (i - N / 2) * h1);
		double y = (R + r * cos(3 * (i - N / 2) * h1)) * sin(2 * (i - N / 2) * h1);
		double z = r * sin(3 * (i - N / 2) * h1);

		glVertex3d(x, y, z);


	}
	glEnd();
*/
	glPopMatrix();
	glFlush();
	glutSwapBuffers();
	time++;
}


//void ProcUp(void)
//{
//	MessageBox(0, L"Up", L"Press", MB_ICONINFORMATION);
//}
void KeyDown(unsigned char key, int x, int y)
{
	//MessageBox(0,L"Up",L"Press",MB_ICONINFORMATION);
	//if ((rotate1 == 0) && (key > '0') && (key < '7')) rotate1 = key - '0';
}
void SpecKeyDown(int key, int x, int y)
{
	//MessageBox(0,L"Up",L"Press",MB_ICONINFORMATION);
	/*
	if (key == GLUT_KEY_DOWN) alfa++;
	if (alfa == 360) alfa = 0;
	if (key == GLUT_KEY_UP) alfa--;
	if (alfa == -1) alfa = 359;

	if (key == GLUT_KEY_RIGHT) beta++;
	if (alfa == 360) beta = 0;
	if (key == GLUT_KEY_LEFT) beta--;
	if (alfa == -1) beta = 359;
	*/
}



void mousefunction(int button, int state, int x, int y)
{
	glBegin(GL_LINES); //
	glVertex2f(0, 0);
	glVertex2f(x, 500 - y);
	glEnd();
	glFlush();
}
void MouseMotion(int x, int y)
{
	float x1, y1, z1;
	//v1*dx,+v2*dy,0
	//ortogon:v1*(-dy)+v2*dx
	x1 = (y - oy) * matrix[0] + (x - ox) * matrix[1];
	y1 = (y - oy) * matrix[4] + (x - ox) * matrix[5];
	z1 = (y - oy) * matrix[8] + (x - ox) * matrix[9];
	glTranslated(0.5, 0, 0.5);
	glRotatef((float)sqrt((x - ox) * (x - ox) + (y - oy) * (y - oy)), x1, y1, z1);
	glTranslated(-0.5f, 0, -0.5);
	ox = x; oy = y;
	glutPostRedisplay();

}
