// I'm drawing the mesh for a hemisphere
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define noOfValues 25

int xRotate = 0;
int yRotate = 0;
int zRotate = 0;

void myInit () {
	
	glClearColor (1.0, 1.0, 1.0, 1.0);
	glEnable (GL_DEPTH_TEST);
	
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity();
	glOrtho (-50.0, 50.0, -50.0, 50.0, -50.0, 0.0);
	glMatrixMode (GL_MODELVIEW);
}

GLfloat sphere (GLfloat x, GLfloat z) {
	
	GLfloat y;

	y = x*x + z*z;
	y = (noOfValues*noOfValues)-y;
	y = sqrtf (y);
	
	return y;
}

void display () {
	
	int i, j;
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glPushMatrix ();
	glRotatef (xRotate, 1.0, 0.0, 0.0);
	glRotatef (yRotate, 0.0, 1.0, 0.0);
	glRotatef (zRotate, 0.0, 0.0, 1.0);
	
	glColor3f (0.0, 0.0, 0.0);
	for (i = -noOfValues+1; i < noOfValues-1; i++)
		for (j = -noOfValues+1; j < noOfValues-1; j++) {
			/* x*x+z*z must not exceed r*r. We must not calclulate
			y for such points, they cannot lie within the sphere.
			The "-2" is for taking into acount floating point comparisons. 	*/
			if (sqrtf(i*i + j*j) >= noOfValues-2)
				continue;
			glBegin (GL_LINE_LOOP);
				glVertex3f (i, sphere (i, j), j);
				glVertex3f (i+1, sphere (i+1, j), j);
				glVertex3f (i+1, sphere (i+1, j+1), (j+1));
				glVertex3f (i, sphere (i, j+1), (j+1));
			glEnd();
		}
	/* we see the height plot only above the x-z plane, i.e positive y-axis.
	I've used the function for a sphere. Only upper hemisphere is seen, for the 
	lower hemisphere, use the above code with "-function()" instead. */
	
	glPopMatrix();
	glFlush();
}

void keyReact (unsigned char key, int x, int y) {
	
	switch (key) {
		case 'x':
			xRotate++; break;
		case 'X':
			xRotate--; break;
		case 'y':
			yRotate++; break;
		case 'Y':
			yRotate--; break;
		case 'z':
			zRotate++; break;
		case 'Z':
			zRotate--; break;
		case 'q':
		case 'Q':
			exit (0);
	}
	glutPostRedisplay();
}

int main (int argc, char *argv[]) {
	
	int i, j;
	
	glutInit (&argc, argv);
	glutInitDisplayMode (GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
	glutCreateWindow ("Mesh");
	glutDisplayFunc (display);
	glutKeyboardFunc (keyReact);
	myInit();
	glutMainLoop();
	
	return 0;
}

