#include <Windows.h>
#include <math.h>

//======    OpenGL
#include <GL\gl.h>
#include <GL\glu.h>
#include <GL\Glaux.h>

//======     
#define Line(x1,y1,x2,y2)		\
	glBegin(GL_LINES);				\
		glVertex2d ((x1),(y1));		\
		glVertex2d ((x2),(y2));		\
	glEnd();

//======    WM_PAINT
void __stdcall OnDraw()
{
	//======    (framebuffer)
	glClear (GL_COLOR_BUFFER_BIT);	
	//======    
	glColor3f (0., 0., 0.);	
	
	//===  1-   3    
	glEnable (GL_LINE_STIPPLE);
	glLineWidth (2.);

	glLineStipple (1, 0x0101);		// dot
	Line (50., 125., 150., 125.);
	glLineStipple (1, 0x00FF);		// dash
	Line (150., 125., 250., 125.);
	glLineStipple (1, 0x1C47);		// dash/dot/dash
	Line (250., 125., 350., 125.);
	
	//======  2-   ,    6 
	glLineWidth (6.);
	glLineStipple (1, 0x0101);		// dot
	Line (50., 100., 150., 100.);
	glLineStipple (1, 0x00FF);		// dash
	Line (150., 100., 250., 100.);
	glLineStipple (1, 0x1C47);		// dash/dot/dash
	Line (250., 100., 350., 100.);
	
	//===  3-  7   
	//===  (strip).    
	glLineWidth (2.);
	glLineStipple (4, 0x1C47);		// dash/dot/dash

	glBegin (GL_LINE_STRIP);
	for (int i = 1; i < 8; i++)
		glVertex2d (50.*i, 75.);
	glEnd();

	//===  4-  6 ,  
	//===   ,      
	for (i = 1;  i < 7; i++)
	{
		Line (50*i, 50, 50*(i+1), 50);
	}

	//======  5-  1     
	glLineStipple (4, 0x1C47);		// dash/dot/dash
	Line (50., 25., 350., 25.);

	glDisable (GL_LINE_STIPPLE);
	glFlush ();
}

//======   WM_SIZE
void __stdcall OnSize (int w, int h)
{
	glViewport (0, 0, (GLsizei) w, (GLsizei) h);
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity();

	//======   
	gluOrtho2D (0.0, double(w), 0.0, double(h));
}

//====== 
void Init()
{
	//======   - 
	glClearColor (1., 1., 1., 0.);
	//======     
	glShadeModel (GL_FLAT);	
}

void main()
{
	//===  pixel-    OpenGL
	auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
	auxInitPosition (200, 200, 550, 250);
	auxInitWindow("My Stipple Test");
	
	Init();
	
	auxReshapeFunc (OnSize);	//    WM_SIZE
	auxMainLoop(OnDraw);		//    WM_PAINT
}


GLubyte gSpade[] = //  - 
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x1f, 0xff, 0xff, 0xf8, 0x1f, 0x00, 0x00, 0xf8,
	0x01, 0xc0, 0x03, 0x80, 0x00, 0x70, 0x0e, 0x00,
	0x00, 0x20, 0x04, 0x00, 0x00, 0x30, 0x0c, 0x00,
	0x00, 0x10, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00,
	0x07, 0xc4, 0x23, 0xe0, 0x0f, 0xf8, 0x1f, 0xf0,
	0x38, 0x1c, 0x38, 0x1c, 0x30, 0x00, 0x00, 0x0c,
	0x60, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x06,
	0x60, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x06,
	0x60, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x0c,
	0x30, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x18,
	0x0e, 0x00, 0x00, 0x70, 0x03, 0x00, 0x00, 0xc0,
	0x00, 0xc0, 0x03, 0x00, 0x00, 0x70, 0x0e, 0x00,
	0x00, 0x18, 0x18, 0x00, 0x00, 0x0c, 0x30, 0x00,
	0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xc0, 0x00,
	0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
};

GLubyte gStrip[] = //   - 
{
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
	0x66, 0x66, 0x66, 0x66, 0x33, 0x33, 0x33, 0x33,
};



void __stdcall OnDraw()
{
	//======  
	glClear (GL_COLOR_BUFFER_BIT);
	//======   ()
	glColor3f (0.3f, 0.3f, 1.);
	
	//===   unstippled rectangle ( )
	//=== Rect -   
	glRectf (20., 20., 115., 120.);

	glColor3f (1., 0., 0.);				//    
	glEnable (GL_POLYGON_STIPPLE);	//  
	glPolygonStipple (gStrip);			//  
	glRectf (120., 20., 215., 120.); // 

	glColor3f (0., 0., 0.);				//    
	glPolygonStipple (gSpade);			//  
	glRectf (220., 20., 315., 120.);

	glPolygonStipple (gStrip);			//  
	glColor3f (0., 0.6f, 0.3f);
	glRectf (320., 20., 415., 120.);

	//===    , 
	//=== (non convex) 
	glPolygonStipple (gSpade);
	glColor3d (0.6, 0.f, 0.3f);

	//======     
	float c[6][3] =
	{
		420.,120.,0.,
		420.,70.,0.,
		470.,20.,0.,
		520., 70.,0.,
		520.,120.,0.,
		470.,100.,0.
	};

	//===     non convex ,
	//===        OpenGL
	glBegin(GL_POLYGON);
		for (int i=0; i<6; i++)
			glVertex3fv(c[i]);
	glEnd();
	glDisable (GL_POLYGON_STIPPLE);
	glFlush ();
}



void __stdcall OnDraw()
{
	glClear (GL_COLOR_BUFFER_BIT);
	glColor3d (1., 0.4, 1.);
	
	//=== 2 ,   
	//=== 2  
	double	pi = 4. * atan(1.),
			a1 = pi / 10.,	a2 = 3. * a1,
			x1 = cos(a1),		y1 = sin(a1),	
			x2 = cos(a2),		y2 = sin(a2);
	
	//===     
	double c[5][3] =	
	{
		 0.,  1., 0.,
		-x2, -y2, 0.,
		 x1,  y1, 0.,
		-x1,  y1, 0.,
		 x2, -y2, 0.,
	};
	
	//======  
	for (int i=0; i<5; i++)
	{
		c[i][0] = 250 + 100*c[i][0];
		c[i][1] = 100 + 100*c[i][1];
	}

	//===    - 
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	//===   
	glBegin(GL_POLYGON);
		for (i=0; i<5; i++)
			glVertex3dv(c[i]);
	glEnd();
	
	glFlush();
}



void __stdcall OnDraw()
{
	glClear (GL_COLOR_BUFFER_BIT);
	glColor3d (1., 0.4, 1.);
	
	//======  ,    
	//======    
	float c[6][3] = 
	{
		200.,200.,0.,
		200.,100.,0.,
		250.,20.,0.,
		300.,100.,0.,
		300.,200.,0.,
		250.,100.,0.,
	};

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	glBegin(GL_QUADS);
		glVertex3fv(c[5]);
		glVertex3fv(c[0]);
		glVertex3fv(c[1]);
		glVertex3fv(c[2]);
		glVertex3fv(c[5]);
		glVertex3fv(c[2]);
		glVertex3fv(c[3]);
		glVertex3fv(c[4]);
	glEnd();

	glFlush ();
}



//======      X  Y
double gdAngleX, gdAngleY;
//======   
double gdTransX, gdTransY, gdTransZ = -4.;



void __stdcall OnDraw()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//===     
	glMatrixMode (GL_MODELVIEW);
	glLoadIdentity ();

	//===      
	glTranslated(gdTransX, gdTransY, gdTransZ);

	//===      
	glRotated(gdAngleY, 0.,1.,0.);
	glRotated(gdAngleX, 1.,0.,0.);

	//======    (   )
	static float v[8][3] =
	{
		-1,   1., -1.,	// 4    
		 1.,  1., -1.,	//     
		 1., -1., -1.,
		-1,  -1., -1.,
		-1,   1.,  1.,	// 4  
		-1., -1.,  1.,
		 1., -1.,  1.,
		 1,   1.,  1.
	};
	
	//====== 6   6-  
	static double norm[6][3] =
	{
		0.,  0., -1.,		// Rear
		0.,  0.,  1.,		// Front
		-1., 0.,  0.,		// Left
		1.,  0.,  0.,		// Right
		0.,  1.,  0.,		// Top
		0., -1.,  0.		// Bottom
	};

	//======   
	static GLuint id[6][4] =
	{
		0,1,2,3,	// Rear ( CCW - counterclockwise)
		4,5,6,7,	// Front
		0,3,5,4,	// Left
		7,6,2,1,	// Right
		0,4,7,1,	// Top
		5,3,2,6,	// Bottom
	};

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glColor3d (1., 0.4, 1.);
	glBegin(GL_QUADS);

	//======   -  
	for (int i = 0; i < 6; i++)
	{
		glNormal3dv(norm[i]);

		for (int j = 0; j < 4; j++) 
			glVertex3fv(v[id[i][j]]);
	}
	glEnd();
	glFlush ();
}



glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);



int Lights;
glGetIntegerv(GL_MAX_LIGHTS, &Lights);
__asm nop



auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSELOC, OnLMouseMove);
auxMouseFunc(AUX_RIGHTBUTTON, AUX_MOUSELOC, OnRMouseMove);
auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSEDOWN, OnButtonDown);
auxMouseFunc(AUX_RIGHTBUTTON, AUX_MOUSEDOWN, OnButtonDown);



static void __stdcall OnButtonDown(AUX_EVENTREC *pEvent)
{
	//======   
	giX = pEvent->data[AUX_MOUSEX];
	giY = pEvent->data[AUX_MOUSEY];
}

static void __stdcall OnLMouseMove(AUX_EVENTREC *pEvent)
{
	//======   
	int x = pEvent->data[AUX_MOUSEX];
	int y = pEvent->data[AUX_MOUSEY];

	//======    
	//======  
	gdAngleX += (y - giY)/10.f;
	gdAngleY += (x - giX)/10.f;

	//======   
	giX = x;
	giY = y;
}

static void __stdcall OnRMouseMove(AUX_EVENTREC *pEvent)
{
	int x = pEvent->data[AUX_MOUSEX];
	int y = pEvent->data[AUX_MOUSEY];

	//======     
	double dx = (x - giX)/200.f;
	double dy = (y - giY)/200.f;

	//======   
	gdTransZ += (dx + dy)/2.f;

	//======   
	giX = x;
	giY = y;
}



	short x = pEvent->data[AUX_MOUSEX];
	short y = pEvent->data[AUX_MOUSEY];



	auxKeyFunc(AUX_DOWN, KeyDown);
	auxKeyFunc(AUX_UP, KeyUp);
	auxKeyFunc(AUX_LEFT, KeyLeft);
	auxKeyFunc(AUX_RIGHT, KeyRight);



void __stdcall KeyDown()
{
	gdTransY -= 0.1;			//   
}

void __stdcall KeyUp()
{
	gdTransY += 0.1;			//   
}

void __stdcall KeyLeft()
{
	gdTransX -= 0.1; 		//   
}

void __stdcall KeyRight()
{
	gdTransX += 0.1;			//   
}



void DrawScene()
{
	//======     OpenGL
	glNewList(1,GL_COMPILE);
		//======   ,  ,
		//======   
		static float v[8][3] =
			. . . . . . .
		//======   
		for (int j = 0; j < 4; j++) 
			glVertex3fv(v[id[i][j]]);
		}
		glEnd();
	glEndList();
}



void __stdcall OnDraw()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode (GL_MODELVIEW);
	glLoadIdentity ();
	glTranslated(gdTransX, gdTransY, gdTransZ);
	glRotated(gdAngleY, 0.,1.,0.);
	glRotated(gdAngleX, 1.,0.,0.);

	//======     1
	glCallList(1);

	auxSwapBuffers();
}



void Init()
{
	glClearColor (1., 1., 1., 0.);
	//======    
	glShadeModel (GL_SMOOTH);

	glEnable(GL_DEPTH_TEST);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_COLOR_MATERIAL);

	//======  
	DrawScene();
}



glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		
glBegin(GL_QUADS);

//======    
srand(time(0));

//====== 6  
for (int i = 0; i < 6; i++)
{
	glNormal3dv(norm[i]);

	//====== 4   
	for (int j = 0; j < 4; j++)
	{
		//======   
		glColor3d (rand()%10/10.,
					rand()%10/10., rand()%10/10.);
		glVertex3fv(v[id[i][j]]);
	}		
}
glEnd();
glEndList();



void DrawScene()
{
	static double
		//====== 2  
		angle = 3. * atan(1.)/2.5,
		V = cos(angle),
		W = sin(angle),

		//====== 12   ( x,y,z)
		v[12][3] =
		{
			{-V,0.,W}, {V,0.,W},  {-V,0.,-W},
			{V,0.,-W}, {0.,W,V},  {0.,W,-V},
			{0.,-W,V}, {0.,-W,-V},{W,V,0.},
			{-W,V,0.}, {W,-V,0.}, {-W,-V,0.}
		};

	//=== 20  ,   
	static GLuint id[20][3] =
	{
		{0,1, 4}, {0,4, 9}, {9,4, 5}, {4,8, 5}, {4,1,8},
		{8,1,10}, {8,10,3}, {5,8, 3}, {5,3, 2}, {2,3,7},
		{7,3,10}, {7,10,6}, {7,6,11}, {11,6,0}, {0,6,1},
		{6,10,1}, {9,11,0}, {9,2,11}, {9,5, 2}, {7,11,2}
	};

	//======    
	glNewList(1,GL_COMPILE);
	//======    
	glColor3d (1., 0.4, 1.);
	glBegin(GL_TRIANGLES);

	for (int i = 0; i < 20; i++)
	{
		//======     
		glNormal3dv(v[id[i][0]]);
		glVertex3dv(v[id[i][0]]);
		
		glNormal3dv(v[id[i][1]]);
		glVertex3dv(v[id[i][1]]);
		
		glNormal3dv(v[id[i][2]]);
		glVertex3dv(v[id[i][2]]);
	}

	glEnd();
	//======   
	glEndList();
}



//===    (  )
void Scale(double v[3])
{
	double d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
	if (d == 0.)
	{
		MessageBox(0,"Zero length vector","Error",MB_OK);
		return;
	}
	v[0] /= d; v[1] /= d; v[2] /= d;
}

void getNorm(double v1[3], double v2[3], double out[3])
{
	//======    
	//======    
	out[0] = v1[1]*v2[2] - v1[2]*v2[1];
	out[1] = v1[2]*v2[0] - v1[0]*v2[2];
	out[2] = v1[0]*v2[1] - v1[1]*v2[0];
	Scale(out);
}



void DrawScene()
{

	static double	
		angle = 3. * atan(1.)/2.5,
		V = cos(angle),
		W = sin(angle),
 
		v[12][3] =
		{
			{-V,0.,W}, {V,0.,W},  {-V,0.,-W},
			{V,0.,-W}, {0.,W,V},  {0.,W,-V},
			{0.,-W,V}, {0.,-W,-V},{W,V,0.},
			{-W,V,0.}, {W,-V,0.}, {-W,-V,0.}
		};

	static GLuint id[20][3] =
	{
		{0,1, 4}, {0,4, 9}, {9,4, 5}, {4,8, 5}, {4,1,8},
		{8,1,10}, {8,10,3}, {5,8, 3}, {5,3, 2}, {2,3,7},
		{7,3,10}, {7,10,6}, {7,6,11}, {11,6,0}, {0,6,1},
		{6,10,1}, {9,11,0}, {9,2,11}, {9,5, 2}, {7,11,2}
	};


	glNewList(1,GL_COMPILE);
	glColor3d (1., 0.4, 1.);
	glBegin(GL_TRIANGLES);

	for (int i = 0; i < 20; i++)
	{
		double d1[3], d2[3], norm[3];
		for (int j = 0; j < 3; j++)
		{
			d1[j] = v[id[i][0]] [j] - v[id[i][1]] [j];
			d2[j] = v[id[i][1]] [j] - v[id[i][2]] [j];
		}
		//======    
		getNorm(d1, d2, norm);
		glNormal3dv(norm);

		glVertex3dv(v[id[i][0]]);
		glVertex3dv(v[id[i][1]]);
		glVertex3dv(v[id[i][2]]);
	}

	glEnd();
	glEndList();
}



//===  OpenGL    
void setTria(double *v1, double *v2, double *v3)
{
	glBegin(GL_TRIANGLES);
		//======      
		glNormal3dv(v1);
		glVertex3dv(v1);
		glNormal3dv(v2);
		glVertex3dv(v2);
		glNormal3dv(v3);
		glVertex3dv(v3);
	glEnd();
}

//======   
void Split(double *v1, double *v2, double *v3)
{
	//======  
	double v12[3], v23[3], v31[3];

	for (int i = 0; i < 3; i++)
	{
		//======    ,
		//======    
		v12[i] = v1[i]+v2[i];
		v23[i] = v2[i]+v3[i];
		v31[i] = v3[i]+v1[i];
	}
	//======    
	Scale(v12);
	Scale(v23);
	Scale(v31);
	//======    
	setTria(v1, v12, v31);
	setTria(v2, v23, v12);
	setTria(v3, v31, v23);
	setTria(v12,v23, v31);
}



void DrawScene()
{
	static double	
		angle = 3. * atan(1.)/2.5,
		V = cos(angle),
		W = sin(angle),

		v[12][3] =
		{
			{-V,0.,W}, {V,0.,W},  {-V,0.,-W},
			{V,0.,-W}, {0.,W,V},  {0.,W,-V},
			{0.,-W,V}, {0.,-W,-V},{W,V,0.},
			{-W,V,0.}, {W,-V,0.}, {-W,-V,0.}
		};

	static GLuint id[20][3] =
	{
		{0,1, 4}, {0,4, 9}, {9,4, 5}, {4,8, 5}, {4,1,8},
		{8,1,10}, {8,10,3}, {5,8, 3}, {5,3, 2}, {2,3,7},
		{7,3,10}, {7,10,6}, {7,6,11}, {11,6,0}, {0,6,1},
		{6,10,1}, {9,11,0}, {9,2,11}, {9,5, 2}, {7,11,2}
	};

	glNewList(1,GL_COMPILE);
	glColor3d (1., 0.4, 1.);
	glBegin(GL_TRIANGLES);

	for (int i = 0; i < 20; i++) 
		Split (v[id[i][0]], v[id[i][1]], v[id[i][2]]); 

	glEnd();
	glEndList();
}



void __stdcall KeyN()
{
	//======    
	gbSmooth = !gbSmooth;
	//======    
	DrawScene();
}



void setTria(double *v1, double *v2, double *v3)
{
	glBegin(GL_TRIANGLES);
	//======      
	if (!gbSmooth)
	{
		//======   
		double d1[3], d2[3], norm[3];

		//======   
		//======   
		for (int j = 0; j < 3; j++)
		{
			d1[j] = v1[j] - v2[j];
			d2[j] = v2[j] - v3[j];
		}
		//======    
		//======    d1  d2
		getNorm(d1, d2, norm);
		glNormal3dv(norm);
		glVertex3dv(v1);
		glVertex3dv(v2);
		glVertex3dv(v3);
	}
	else
	{
		//===  ()  
		glNormal3dv(v1);
		glVertex3dv(v1);
		glNormal3dv(v2);
		glVertex3dv(v2);
		glNormal3dv(v3);
		glVertex3dv(v3);
	}
	glEnd();
}



void Split(double *v1, double *v2, double *v3,	long depth)
{
	double v12[3], v23[3], v31[3];

	if (depth == 0)
	{
		//======   
		setTria(v1, v2, v3);
		//======      
		return;
	}

	//======  
	for (int i = 0; i < 3; i++)
	{
		v12[i] = v1[i]+v2[i];
		v23[i] = v2[i]+v3[i];
		v31[i] = v3[i]+v1[i];
	}

	//======   
	Scale(v12);
	Scale(v23);
	Scale(v31);
	//======   
	//======   
	Split(v1, v12, v31, depth-1);
	Split(v2, v23, v12, depth-1);
	Split(v3, v31, v23, depth-1);
	Split(v12, v23, v31, depth-1);
}



void __stdcall KeySpace()
{
	//======    
	static bool bGrow = true;
	
	//======     4
	if (bGrow && giDepth < 4)
	{
		giDepth += 1;
	}
	//======     4
	else if (giDepth > 0)
	{
		bGrow = false;
		giDepth -= 1;
	}
	//======     0
	else
	{
		bGrow = true;
		giDepth += 1;
	}

	DrawScene();
}



//======   1- ,
if (glIsList(1))
		//======   
		glDeleteLists(1,1);



#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>

const UINT gnRings = 40;		//   ()
const UINT gnSects = 40;		//   ()

//======   
const UINT gnTria = (gnRings+1) * gnSects * 2;

//======   
const UINT gnVert = (gnRings+1) * gnSects + 2;

//======   
const COLORREF gClr1 = RGB(0, 255, 0);
const COLORREF gClr2 = RGB(0, 0, 255);

const double gRad = 1.5;			//  
const double gMax = 5.;			//  
const double PI = atan(1.)*4.; //  



//======  3D-
class CPoint3D	
{
public:
	float x, y, z;	//  

	//======   
	CPoint3D () { x = y = z = 0; }
	//======   
	CPoint3D (double c1, double c2, float c3)
	{
		x = float(c1);
		z = float(c2);
		y = float(c3);
	}

	//======  
	CPoint3D& operator=(const CPoint3D& pt)
	{
		x = pt.x;
		z = pt.z;
		y = pt.y;
		return *this;
	}
	
	//======    
	CPoint3D& operator+=(const CPoint3D& pt)
	{
		x += pt.x;
		y += pt.y;
		z += pt.z;
		return *this;
	}	

	//======  
	CPoint3D (const CPoint3D& pt)
	{
		*this = pt;
	}
};



//======     
struct VERT
{
	CPoint3D v;	//  
	CPoint3D n;	//  
	DWORD c;		//  
};



struct TRIA
{
	//======    ,
	//======      VERT
	//======   -   
	int i1;
	int i2;
	int i3;
};



//======      
CPoint3D gSpin;
//======     gSpin
CPoint3D gShift;



inline double Rand(double x)
{
	//======     (-x, x)
	return x - (x + x) * rand() / RAND_MAX;
}



void __stdcall OnDraw()
{
	glClear(GL_COLOR_BUFFER_BIT);
	//===     
	glLoadIdentity();

	//======  	
	glRotated(gSpin.x, 1., 0,  0.);
	glRotated(gSpin.y, 0., 1., 0.);
	glRotated(gSpin.z, 0., 0., 1.);

	//======    	
	glCallList(1);
	
	//======    
	gSpin += gShift;
	
	//======  
	auxSwapBuffers();
}



void Init()
{
	//===   (    )
	glClearColor (0., 0., 0., 0.);

	//======    
	glEnable(GL_LIGHTING);
	//======      
	glEnable(GL_LIGHT0);
	//======     
	glEnable(GL_COLOR_MATERIAL);

	//      
	float v[4] =
	{
		0.05f, 0.05f, 0.05f, 1.f
	};

	//===     
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, v);

	//======  
	v[0] = 0.9f;
	v[1] = 0.9f;
	v[2] = 0.9f;

	//======    
	glLightfv(GL_LIGHT0, GL_DIFFUSE, v);

	//=======  
	v[0] = 0.6f;
	v[1] = 0.6f;
	v[2] = 0.6f;

	//======    
	glMaterialfv(GL_FRONT, GL_SPECULAR, v);

	//======    
	glMateriali(GL_FRONT, GL_SHININESS, 40);

	//======  
	v[0] = 0.f;
	v[1] = 0.f;
	v[2] = 1.f;
	v[3] = 0.f;

	//======    
	glLightfv(GL_LIGHT0, GL_POSITION, v);

	//======    
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	//======   
	gluPerspective(45, 1, .01, 15);

	//===   ,  
	//===      z  8 
	gluLookAt(0, 0, 8, 0, 0, 0, 0, 1, 0);

	//======    
	glMatrixMode(GL_MODELVIEW);

	//======     
	glEnable(GL_CULL_FACE);
	//======     
	glCullFace(GL_BACK);
	
	//======  OpenGL   
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	
	//======     
	VERT *Vert = new VERT[gnVert];
	TRIA *Tria = new TRIA[gnTria];

	//======  
	Sphere(Vert, Tria);
	
	//======     (,
	//======   ),
	//======      
	glVertexPointer(3, GL_FLOAT, sizeof(VERT), &Vert->v);
	glNormalPointer(GL_FLOAT, sizeof(VERT), &Vert->n);
	glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VERT),
													&Vert->c);
	
	srand(time(0));		//  
	gShift = CPoint3D (Rand(gMax),Rand(gMax),Rand(gMax));

	//======    
	glNewList(1, GL_COMPILE);
		glDrawElements(GL_TRIANGLES, gnTria*3,
							GL_UNSIGNED_INT, Tria);
	glEndList();

	//==  ,    
	delete [] Vert;
	delete [] Tria;
}



void Sphere(VERT *v, TRIA* t)
{
	//======   
	//======  
	v[0].v = CPoint3D (0, gRad, 0);
	v[0].n = CPoint3D (0, 1, 0);
	v[0].c = gClr2;

	//======    (  )
	UINT last = gnVert - 1;
	//======  
	v[last].v = CPoint3D (0, -gRad, 0);
	v[last].n = CPoint3D (0, -1, 0);
	v[last].c = gnVert & 1 ? gClr2 : gClr1;

	//======  
	double	da = PI / (gnRings + 2.),
			db = 2. * PI / gnSects,
			af = PI - da/2.,
			bf = 2. * PI - db/2.;

	//===  ,    
	UINT n = 1;
	//===   
	for (double a = da;  a < af;  a += da)
	{
		//===  y    
		double	y  = gRad * cos(a),
				//======  
				xz = gRad * sin(a);

		//======    ()
		for (double b = 0.; b < bf; n++, b += db)
		{
			//     
			double	x = xz * sin(b),
					z = xz * cos(b);

			//====== ,   
			v[n].v = CPoint3D (x, y, z);
			v[n].n = CPoint3D (x / gRad, y / gRad, z / gRad);
			v[n].c = n & 1 ? gClr1 : gClr2;
		}
	}

	//======   
	//======   
	for (n = 0; n < gnSects; n++)
	{
		//======    ( )
		t[n].i1 = 0;
		//======   
		t[n].i2 = n + 1;
		//====== 
		t[n].i3 = n == gnSects - 1 ? 1 : n + 2;
		//======    ( )
		t[gnTria-gnSects+n].i1 = gnVert - 1;
		t[gnTria-gnSects+n].i2 = gnVert - 2 - n;
		t[gnTria-gnSects+n].i3 = gnVert - 2
								- ((1 + n) % gnSects);
	}
	
	//======   
	//====== ,   
	int k = 1;

	//====== gnSects -   
	n = gnSects;
	for (UINT i = 0; i < gnRings; i++, k += gnSects)
	{
		for (UINT j = 0; j < gnSects; j++, n += 2)
		{
			//=======   
			t[n].i1 = k + j;
			//=======   
			t[n].i2 = k + gnSects + j;
			//======= 
			t[n].i3 = k + gnSects + ((j + 1) % gnSects);
			//=======     
			t[n + 1].i1 = t[n].i1;
			t[n + 1].i2 = t[n].i3;
			t[n + 1].i3 = k + ((j + 1) % gnSects);
		}
	}
}



void __stdcall OnSize(GLsizei w, GLsizei h)
{
	glViewport(0, 0, w, h);
}

void main()
{
	auxInitDisplayMode(AUX_RGB | AUX_DOUBLE);
	auxInitPosition(10, 10, 512, 512);
	auxInitWindow("Vertex Array");

	Init();

	auxReshapeFunc(OnSize);
	auxIdleFunc(OnDraw);
	auxMainLoop(OnDraw);
}




