Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 10

Thread: Turn a function plot in 2D directly into 3D

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19

    Turn a function plot in 2D directly into 3D

    I have the following opengl app which plots 2d funxtions. I want to turn it into one for plotting 3D surfaces with min. changes that is maintain the drawVertex and just change the projection. I was unable to do that as shown in the code...

    First Here is the 2D function plot:

    #include <math.h>
    #include <GL\glut.h>

    const int SCREENWIDTH = 640;
    const int SCREENHEIGHT = 640;

    GLdouble A, B, C, D;
    GLdouble minX = -1.0, maxX = 1.0;
    GLdouble minF = -1.0, maxF = 1.0;

    void myInit(void) {
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glColor3f(0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)SCREENWIDTH, 0.0, (GLdouble)SCREENHEIGHT);
    A = SCREENWIDTH/(maxX-minX);
    B = -minX * SCREENWIDTH/(maxX-minX);
    C = SCREENHEIGHT/(maxF-minF);
    D = -minF * SCREENHEIGHT/(maxF-minF);
    }

    void myDisplay(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_LINE_STRIP);
    for (GLdouble a=0.0; a<2.0*3.14159265; a+=0.001) {
    // GLdouble x = (10.0+sin(15.0*a)) * cos(a);
    // GLdouble f = (10.0+sin(15.0*a)) * sin(a);
    GLdouble r = sin(2.0*a);
    GLdouble x = r * cos(a);
    GLdouble f = r * sin(a);
    glVertex2d(A*x+B, C*f+D);
    }
    glEnd();
    glFlush();
    }

    int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(SCREENWIDTH, SCREENHEIGHT);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Function Plot");
    glutDisplayFunc(myDisplay);
    myInit();
    glutMainLoop();
    return 0;
    }


    Now here is my unsuccessful attempt:

    #include <math.h>
    #include <GL\glut.h>

    const int SCREENWIDTH = 640;
    const int SCREENHEIGHT = 640;

    GLdouble A, B, C, D, E, F;
    GLdouble minX = -1.0, maxX = 1.0;
    GLdouble minY = -1.0, maxY = 1.0;
    GLdouble minF = 1.0, maxF = 3.0;

    void myInit(void) {
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glColor3f(0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // gluOrtho2D(0.0, (GLdouble)SCREENWIDTH, 0.0, (GLdouble)SCREENHEIGHT);
    glOrtho(0.0,(GLdouble)SCREENHEIGHT,0.0,(GLdouble)S CREENWIDTH,0.0,(GLdouble)SCREENWIDTH);
    //glFrustum(0.0,(GLdouble)SCREENHEIGHT,0.0,(GLdouble )SCREENWIDTH,0.0,(GLdouble)SCREENWIDTH);
    //gluPerspective(45,1.0,0.5,3.5);
    A = SCREENHEIGHT/(maxX-minX);
    B = -minX * SCREENHEIGHT/(maxX-minX);
    C = SCREENWIDTH/(maxY-minY);
    D = -minY * SCREENWIDTH/(maxY-minY);
    E = SCREENWIDTH/(maxF-minF);
    F = -minF * SCREENWIDTH/(maxF-minF);
    //glMatrixMode(GL_MODELVIEW);
    // glLoadIdentity();
    // gluLookAt(0,0,0,-1.5,-1.5,0,0.0,0.0,1.0);
    glEnable(GL_DEPTH_TEST);
    }

    void myDisplay(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_LINE_STRIP);
    for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    GLdouble /*x*/f = t*(u*u - t*t)+2.0;
    GLdouble /*y*/x = u;
    GLdouble /*f*/y = u*u - t*t;
    // glPushMatrix();
    // glRotatef(90.0,0.0,1.0,0.0);
    glVertex3d(A*x+B, C*y+D, E*f+F);
    // glPopMatrix();
    }
    }
    glEnd();
    glFlush();
    }

    int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(SCREENWIDTH, SCREENHEIGHT);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("3D Function Plot");
    glutDisplayFunc(myDisplay);
    myInit();
    glutMainLoop();
    return 0;
    }

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    754
    Please use [code][/code] around source code. I'm not really sure what you are asking, for example what is drawVertex that you don't want to change? I'd doubt it is possible to avoid making quite substantial changes since surfaces have an additional dimension compared to the lines you are currently drawing. Anyway, can you clarify what you are after?

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    Quote Originally Posted by carsten neumann View Post
    Please use [code][/code] around source code. I'm not really sure what you are asking, for example what is drawVertex that you don't want to change? I'd doubt it is possible to avoid making quite substantial changes since surfaces have an additional dimension compared to the lines you are currently drawing. Anyway, can you clarify what you are after?
    I meant use glVertex3d instead of glVertex2d, that is draw the surface one point at a time. This is shown in the attached code.

    Here is the 2D code which is working fine:

    Code :
    #include <math.h>
    #include <GL\glut.h>
     
    const int SCREENWIDTH = 640;
    const int SCREENHEIGHT = 640;
     
    GLdouble A, B, C, D;
    GLdouble minX = -1.0, maxX = 1.0;
    GLdouble minF = -1.0, maxF = 1.0;
     
    void myInit(void) {
    	glClearColor(1.0, 1.0, 1.0, 0.0);
    	glColor3f(0.0, 0.0, 0.0);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(0.0, (GLdouble)SCREENWIDTH, 0.0, (GLdouble)SCREENHEIGHT);
    	A = SCREENWIDTH/(maxX-minX);
    	B = -minX * SCREENWIDTH/(maxX-minX);
    	C = SCREENHEIGHT/(maxF-minF);
    	D = -minF * SCREENHEIGHT/(maxF-minF);
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT);
    	glBegin(GL_LINE_STRIP);
    	for (GLdouble a=0.0; a<2.0*3.14159265; a+=0.001) {
    	  //		GLdouble x = (10.0+sin(15.0*a)) * cos(a);
    	  //	GLdouble f = (10.0+sin(15.0*a)) * sin(a);
    	  GLdouble r = sin(2.0*a);
    	  GLdouble x = r * cos(a);
    	  GLdouble f = r * sin(a);
    	  glVertex2d(A*x+B, C*f+D);
    	}
    	glEnd();
    	glFlush();
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    	glutInitWindowSize(SCREENWIDTH, SCREENHEIGHT);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("Function Plot");
    	glutDisplayFunc(myDisplay);
    	myInit();
    	glutMainLoop();
    	return 0;
    }

    and Here is my attempt at the 3D case:

    Code :
    #include <math.h>
    #include <GL\glut.h>
     
    const int SCREENWIDTH = 640;
    const int SCREENHEIGHT = 640;
     
    GLdouble A, B, C, D, E, F;
    GLdouble minX = -1.0, maxX = 1.0;
    GLdouble minY = -1.0, maxY = 1.0;
    GLdouble minF = 1.0, maxF = 3.0;
     
    void myInit(void) {
    	glClearColor(1.0, 1.0, 1.0, 0.0);
    	glColor3f(0.0, 0.0, 0.0);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	//		gluOrtho2D(0.0, (GLdouble)SCREENWIDTH, 0.0, (GLdouble)SCREENHEIGHT);
    		glOrtho(0.0,(GLdouble)SCREENHEIGHT,0.0,(GLdouble)SCREENWIDTH,0.0,(GLdouble)SCREENWIDTH);
    		//glFrustum(0.0,(GLdouble)SCREENHEIGHT,0.0,(GLdouble)SCREENWIDTH,0.0,(GLdouble)SCREENWIDTH);
    		//gluPerspective(45,1.0,0.5,3.5);
    		A = SCREENHEIGHT/(maxX-minX);
    		B = -minX * SCREENHEIGHT/(maxX-minX);
    		C = SCREENWIDTH/(maxY-minY);
    		D = -minY * SCREENWIDTH/(maxY-minY);
    		E = SCREENWIDTH/(maxF-minF);
    		F = -minF * SCREENWIDTH/(maxF-minF);
    		//glMatrixMode(GL_MODELVIEW);
    		// glLoadIdentity();
    		// gluLookAt(0,0,0,-1.5,-1.5,0,0.0,0.0,1.0);
    		glEnable(GL_DEPTH_TEST);
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT);
    	glBegin(GL_LINE_STRIP);
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    GLdouble /*x*/f = t*(u*u - t*t)+2.0;
    	    GLdouble /*y*/x = u;
    	  GLdouble /*f*/y = u*u - t*t;
    	  //	  glPushMatrix();
    	  //	  glRotatef(90.0,0.0,1.0,0.0);
    	  glVertex3d(A*x+B, C*y+D, E*f+F);
    	  //	  glPopMatrix();
    	}
    	}
    	glEnd();
    	glFlush();
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(SCREENWIDTH, SCREENHEIGHT);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	glutDisplayFunc(myDisplay);
    	myInit();
    	glutMainLoop();
    	return 0;
    }

  4. #4
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    I think I found what is wrong, I had nothing appearing because in 3d the camera is aiming at the -ve z axis not the +ve axis which I have been assuming translating by glTranslatef(0.0,0.0,-MAXF) will make something appear although not so good looking, no depth cues....

  5. #5
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    Here is the code working after adding zooming and rotation to the surface, but what I still don't know how to do is to determine the sides of the surface to be colored by 2 different colors in order to be able to see the folds. I can compute the surface normal at every vertex but don't know how to use it to differentiate the sides?


    Code :
    #include <math.h>
    #include <GL\glut.h>
     
     
    	GLint ww=500, wh=500;
    	GLfloat scale;
    	int gbtn, gstate;
    void colorcube()
    {
    	glBegin(GL_POINTS);
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    GLdouble /*x*/f = t*(u*u - t*t);
    	    GLdouble /*y*/x = u;
    	  GLdouble /*f*/y = u*u - t*t;
    	  //	  glPushMatrix();
    	  //	  glRotatef(90.0,0.0,1.0,0.0);
    	  glVertex3d(x, y, f);
    	  //	  glPopMatrix();
    	}
    	}
    	glEnd();
    }
     
    static GLfloat theta[] = {0.0,0.0,0.0};
     
    static GLdouble viewer[]= {0.0, 0.0, 12.0}; /* initial viewer location */
     
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    /* Update viewer position in modelview matrix */
     
    	glLoadIdentity();
    	//gluLookAt(viewer[0],viewer[1],viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     
    /* rotate cube */
     
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
     
     colorcube();
    /* Use a perspective view */
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
    	else if(gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else { /* Move Camera closer to the cube */
    			if ((((x-xp)>=0) && ((-y+yp)>=0)) || (((x-xp)>=0) && ((-y+yp)<0) && ((abs(y-yp))<(x-xp)))
    				|| ((((x-xp)<0) && ((-y+yp)>=0) && ((abs(x-xp))<(-y+yp))))) {
    				viewer[2] -= 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				//printf("%f\n",viewer[2]);
    				if(viewer[2]<=4.8)viewer[2]=4.8;
    				xp=x;
    				yp=y;
    			myDisplay();
     
    				return;
    			}
    			else { /* Move Camera farther from the cube */
    				viewer[2] += 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				if (viewer[2]>=18.2) viewer[2]=18.2;
    				//printf("%f\n",viewer[2]);
    				xp=x;
    				yp=y;
    				myDisplay();
     
    				return;
    			}
    		}
    	}
    	else if (gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
    	else if(gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			viewer[0] += 0.035*(-x+xp); 
    			//if (fabs(viewer[0])> 1.2) viewer[0] = 1.2 * (viewer[0] >0?1:-1);
     
    			viewer[1] += 0.035*(y-yp);  
    			//if (fabs(viewer[1]) > 1.2) viewer[1] = 1.2 * (viewer[1] >0?1:-1);
     
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;
    		}
    	}
    	else if (gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
     
    	myDisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
    /* Use a perspective view */
    	glClearColor(1.0, 1.0, 1.0, 0.0);
    	glColor3f(0.0, 0.0, 0.0);
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) glFrustum(-1.8, 1.8, -1.8 * (GLfloat) h/ (GLfloat) w, 
           1.8* (GLfloat) h / (GLfloat) w, 2.0, 24.0);
    	else glFrustum(-1.8* (GLfloat) w/ (GLfloat) h, 1.8* (GLfloat) w/ (GLfloat) h, -1.8,
           1.8, 2.0, 24.0);
     
    /* Or we can use gluPerspective */
     
    // gluPerspective(45.0, w/h, -4.0, 4.0); 
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glEnable(GL_DEPTH_TEST);
    	glShadeModel(GL_FLAT);
    	glutMainLoop();
    	return 0;
    }

  6. #6
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    Well I used lighting and defined it to use both sides of the surface and defined the normal at each vertex but what I get is the front surface and the back surface is invisible, what I want is to display the back surface in a different color or shade from the front surface not to be invisible....any help?

    Code :
    #include <math.h>
    #include <GL\glut.h>
     
     
    	GLint ww=500, wh=500;
    	GLfloat scale;
    	int gbtn, gstate;
    static GLfloat theta[] = {0.0,0.0,0.0};
    static GLfloat normals[3];
    static GLfloat viewer[]= {0.0, 0.0, 10.0}; /* initial viewer location */
     
    void init(void)
    {
    GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };
    GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat lmodel_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glLightfv(GL_LIGHT0, GL_POSITION, viewer);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
    glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    }
     
    void colorcube()
    {
    	glBegin(GL_POINTS);
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    GLdouble /*x*/f = t*(u*u - t*t);
    	    GLdouble /*y*/x = u;
    	  GLdouble /*f*/y = u*u - t*t;
    	  //	  glPushMatrix();
    	  //	  glRotatef(90.0,0.0,1.0,0.0);
    	  normals[0] = 2.0 * x;
    	  normals[1] = 2.0 * y * f * f;
    	  normals[2] = 2.0 * y * y * f + 3.0 * f * f;
    		glNormal3fv(normals);
    	  glVertex3d(x, y, f);
    	  //	  glPopMatrix();
    	}
    	}
    	glEnd();
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    /* Update viewer position in modelview matrix */
    glLightfv(GL_LIGHT0, GL_POSITION, viewer);
    	glLoadIdentity();
    	//gluLookAt(viewer[0],viewer[1],viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     
    /* rotate cube */
     
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
     
     colorcube();
    /* Use a perspective view */
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'X':theta[0]+=1;
    	  if (theta[0]==360) theta[0]=0;
    	  myDisplay();
    	  break;
    	case 'x': theta[0]-=1;
    	  if (theta[0]<0) theta[0] = 359;
    	  myDisplay();
    	  break;
    	case 'Y':theta[1]+=1;
    	  if (theta[1]==360) theta[1]=0;
    	  myDisplay();
    	  break;
    	case 'y': theta[1]-=1;
    	  if (theta[1]<0) theta[1] = 359;
    	  myDisplay();
    	  break;
    	case 'Z':theta[2]+=1;
    	  if (theta[2]==360) theta[2]=0;
    	  myDisplay();
    	  break;
    	case 'z': theta[2]-=1;
    	  if (theta[2]<0) theta[2] = 359;
    	  myDisplay();
    	  break;
    	case '+':
    	  viewer[2] -= 0.5;
    	  if (viewer[2]<=1.0) viewer[2] = 1.5;
    	  break;
    	case '-':
    	  viewer[2] += 0.5;
    	  if (viewer[2]>=10.0) viewer[2] = 10.0;
    				 break;
    	}
    	glutPostRedisplay ();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
    	else if(gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else { /* Move Camera closer to the cube */
    			if ((((x-xp)>=0) && ((-y+yp)>=0)) || (((x-xp)>=0) && ((-y+yp)<0) && ((abs(y-yp))<(x-xp)))
    				|| ((((x-xp)<0) && ((-y+yp)>=0) && ((abs(x-xp))<(-y+yp))))) {
    				viewer[2] -= 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				//printf("%f\n",viewer[2]);
    				if(viewer[2]<=4.8)viewer[2]=4.8;
    				xp=x;
    				yp=y;
    			myDisplay();
     
    				return;
    			}
    			else { /* Move Camera farther from the cube */
    				viewer[2] += 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				if (viewer[2]>=18.2) viewer[2]=18.2;
    				//printf("%f\n",viewer[2]);
    				xp=x;
    				yp=y;
    				myDisplay();
     
    				return;
    			}
    		}
    	}
    	else if (gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
    	else if(gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			viewer[0] += 0.035*(-x+xp); 
    			//if (fabs(viewer[0])> 1.2) viewer[0] = 1.2 * (viewer[0] >0?1:-1);
     
    			viewer[1] += 0.035*(y-yp);  
    			//if (fabs(viewer[1]) > 1.2) viewer[1] = 1.2 * (viewer[1] >0?1:-1);
     
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;
    		}
    	}
    	else if (gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
     
    	myDisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
    /* Use a perspective view */
    	glClearColor(0.0, 0.0, 0.0, 0.0);
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) glFrustum(-1.8, 1.8, -1.8 * (GLfloat) h/ (GLfloat) w, 
           1.8* (GLfloat) h / (GLfloat) w, 2.0, 24.0);
    	else glFrustum(-1.8* (GLfloat) w/ (GLfloat) h, 1.8* (GLfloat) w/ (GLfloat) h, -1.8,
           1.8, 2.0, 24.0);
     
    /* Or we can use gluPerspective */
     
    // gluPerspective(45.0, w/h, -4.0, 4.0); 
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	init();
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glutKeyboardFunc(keyboard);
    	glEnable(GL_DEPTH_TEST);
    	glShadeModel(GL_SMOOTH);
    	glutMainLoop();
    	return 0;
    }

  7. #7
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    OK I defined different material colors for the front and back sides but still get white for both sides even though the back has material color red...??

    Code :
    #include <math.h>
    #include <GL\glut.h>
     
     
    	GLint ww=500, wh=500;
    	GLfloat scale;
    	int gbtn, gstate;
    static GLfloat theta[] = {0.0,0.0,0.0};
    static GLfloat normals[3];
    static GLfloat viewer[]= {0.0, 0.0, 10.0}; /* initial viewer location */
     
    void init(void)
    {
    GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_b_ambient[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat lmodel_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
     glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
     glMaterialfv(GL_BACK, GL_AMBIENT, mat_b_ambient);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);
    }
     
    void surface()
    {
    	glBegin(GL_POINTS);
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    GLdouble /*x*/f = t*(u*u - t*t);
    	    GLdouble /*y*/x = u;
    	  GLdouble /*f*/y = u*u - t*t;
    	  normals[0] = 2.0 * x;
    	  normals[1] = 2.0 * y * f * f;
    	  normals[2] = 2.0 * y * y * f + 3.0 * f * f;
    		glNormal3fv(normals);
    	  glVertex3d(x, y, f);
    	}
    	}
    	glEnd();
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	glLoadIdentity();
     
    /* rotate surface */
     
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
    	glRotatef(theta[2], 0.0, 0.0, 1.0);
    surface();
    /* Use a perspective view */
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'X':theta[0]+=1;
    	  if (theta[0]==360) theta[0]=0;
    	  myDisplay();
    	  break;
    	case 'x': theta[0]-=1;
    	  if (theta[0]<0) theta[0] = 359;
    	  myDisplay();
    	  break;
    	case 'Y':theta[1]+=1;
    	  if (theta[1]==360) theta[1]=0;
    	  myDisplay();
    	  break;
    	case 'y': theta[1]-=1;
    	  if (theta[1]<0) theta[1] = 359;
    	  myDisplay();
    	  break;
    	case 'Z':theta[2]+=1;
    	  if (theta[2]==360) theta[2]=0;
    	  myDisplay();
    	  break;
    	case 'z': theta[2]-=1;
    	  if (theta[2]<0) theta[2] = 359;
    	  myDisplay();
    	  break;
    	case '+':
    	  viewer[2] -= 0.5;
    	  if (viewer[2]<=1.0) viewer[2] = 1.5;
    	  break;
    	case '-':
    	  viewer[2] += 0.5;
    	  if (viewer[2]>=10.0) viewer[2] = 10.0;
    				 break;
    	}
    	glutPostRedisplay ();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
    	else if(gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else { /* Move Camera closer to the cube */
    			if ((((x-xp)>=0) && ((-y+yp)>=0)) || (((x-xp)>=0) && ((-y+yp)<0) && ((abs(y-yp))<(x-xp)))
    				|| ((((x-xp)<0) && ((-y+yp)>=0) && ((abs(x-xp))<(-y+yp))))) {
    				viewer[2] -= 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				//printf("%f\n",viewer[2]);
    				if(viewer[2]<=4.8)viewer[2]=4.8;
    				xp=x;
    				yp=y;
    			myDisplay();
     
    				return;
    			}
    			else { /* Move Camera farther from the cube */
    				viewer[2] += 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				if (viewer[2]>=18.2) viewer[2]=18.2;
    				//printf("%f\n",viewer[2]);
    				xp=x;
    				yp=y;
    				myDisplay();
     
    				return;
    			}
    		}
    	}
    	else if (gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
    	else if(gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			viewer[0] += 0.035*(-x+xp); 
    			//if (fabs(viewer[0])> 1.2) viewer[0] = 1.2 * (viewer[0] >0?1:-1);
     
    			viewer[1] += 0.035*(y-yp);  
    			//if (fabs(viewer[1]) > 1.2) viewer[1] = 1.2 * (viewer[1] >0?1:-1);
     
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;
    		}
    	}
    	else if (gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
     
    	myDisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
    /* Use a perspective view */
    	glClearColor(0.0, 0.0, 0.0, 0.0);
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) glFrustum(-2.4, 2.4, -2.4 * (GLfloat) h/ (GLfloat) w, 
           2.4* (GLfloat) h / (GLfloat) w, 2.0, 24.0);
    	else glFrustum(-2.4* (GLfloat) w/ (GLfloat) h, 2.4* (GLfloat) w/ (GLfloat) h, -2.4,2.4, 2.0, 24.0);
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	init();
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glutKeyboardFunc(keyboard);
    	glutMainLoop();
    	return 0;
    }

  8. #8
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    I fixed the calculation of the normal and set the order of x, y, and f correctly and still back and front sides white? any help??
    Here is the final code:
    Code :
    #include <math.h>
    #include <GL\glut.h>
     
     
    	GLint ww=500, wh=500;
    	GLfloat scale;
    	int gbtn, gstate;
    static GLfloat theta[] = {0.0,0.0,0.0};
    static GLfloat normals[3];
    static GLfloat viewer[]= {0.0, 0.0, 10.0}; /* initial viewer location */
     
    void init(void)
    {
    GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_b_ambient[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat lmodel_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
     glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
     glMaterialfv(GL_BACK, GL_AMBIENT, mat_b_ambient);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);
    }
     
    void surface()
    {
    	glBegin(GL_POINTS);
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    GLdouble x = t*(u*u - t*t);
    	    GLdouble y = u;
    	  GLdouble f = u*u - t*t;
    	  //x^2 - y^2 * Z^2 + Z^3 = 0
    	  normals[0] = 2.0 * x;
    	  normals[1] = -2.0 * y * f * f;
    	  normals[2] = -2.0 * y * y * f + 3.0 * f * f;
    		glNormal3fv(normals);
    	  glVertex3d(x, y, f);
    	}
    	}
    	glEnd();
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	glLoadIdentity();
     
    /* rotate surface */
     
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
    	glRotatef(theta[2], 0.0, 0.0, 1.0);
    surface();
    /* Use a perspective view */
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'X':theta[0]+=1;
    	  if (theta[0]==360) theta[0]=0;
    	  myDisplay();
    	  break;
    	case 'x': theta[0]-=1;
    	  if (theta[0]<0) theta[0] = 359;
    	  myDisplay();
    	  break;
    	case 'Y':theta[1]+=1;
    	  if (theta[1]==360) theta[1]=0;
    	  myDisplay();
    	  break;
    	case 'y': theta[1]-=1;
    	  if (theta[1]<0) theta[1] = 359;
    	  myDisplay();
    	  break;
    	case 'Z':theta[2]+=1;
    	  if (theta[2]==360) theta[2]=0;
    	  myDisplay();
    	  break;
    	case 'z': theta[2]-=1;
    	  if (theta[2]<0) theta[2] = 359;
    	  myDisplay();
    	  break;
    	case '+':
    	  viewer[2] -= 0.5;
    	  if (viewer[2]<=1.0) viewer[2] = 1.5;
    	  break;
    	case '-':
    	  viewer[2] += 0.5;
    	  if (viewer[2]>=10.0) viewer[2] = 10.0;
    				 break;
    	}
    	glutPostRedisplay ();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
    	else if(gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else { /* Move Camera closer to the cube */
    			if ((((x-xp)>=0) && ((-y+yp)>=0)) || (((x-xp)>=0) && ((-y+yp)<0) && ((abs(y-yp))<(x-xp)))
    				|| ((((x-xp)<0) && ((-y+yp)>=0) && ((abs(x-xp))<(-y+yp))))) {
    				viewer[2] -= 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				//printf("%f\n",viewer[2]);
    				if(viewer[2]<=4.8)viewer[2]=4.8;
    				xp=x;
    				yp=y;
    			myDisplay();
     
    				return;
    			}
    			else { /* Move Camera farther from the cube */
    				viewer[2] += 0.1*sqrt((x-xp)*(x-xp) + (y-yp)*(y-yp));
    				if (viewer[2]>=18.2) viewer[2]=18.2;
    				//printf("%f\n",viewer[2]);
    				xp=x;
    				yp=y;
    				myDisplay();
     
    				return;
    			}
    		}
    	}
    	else if (gbtn==GLUT_RIGHT_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
    	else if(gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			viewer[0] += 0.035*(-x+xp); 
    			//if (fabs(viewer[0])> 1.2) viewer[0] = 1.2 * (viewer[0] >0?1:-1);
     
    			viewer[1] += 0.035*(y-yp);  
    			//if (fabs(viewer[1]) > 1.2) viewer[1] = 1.2 * (viewer[1] >0?1:-1);
     
    			xp=x;
    			yp=y;
    			myDisplay();
    			return;
    		}
    	}
    	else if (gbtn==GLUT_MIDDLE_BUTTON && gstate == GLUT_UP) {
    		t=0;
    		return;
    	}
     
    	myDisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
    /* Use a perspective view */
    	glClearColor(0.0, 0.0, 0.0, 0.0);
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) glFrustum(-2.4, 2.4, -2.4 * (GLfloat) h/ (GLfloat) w, 
           2.4* (GLfloat) h / (GLfloat) w, 2.0, 24.0);
    	else glFrustum(-2.4* (GLfloat) w/ (GLfloat) h, 2.4* (GLfloat) w/ (GLfloat) h, -2.4,2.4, 2.0, 24.0);
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	init();
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glutKeyboardFunc(keyboard);
    	glutMainLoop();
    	return 0;
    }

  9. #9
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19

    Final Version in case anybody is interested

    The code plots a surface with -1<=x<=1, -1<=y<=1< -1<=z<=1 in parametric form.
    It allows rotating to see the surface from different viewpoints... Of course this could generalize to any ranges. The only problem is the choice of colors of the surface, probably turning the displayed color into shades of gray would look better....

    Code :
    #include <math.h>
    #include <GL\glut.h>
     
    	GLint ww=500, wh=500;
    	int gbtn, gstate;
    static GLfloat theta[] = {0.0,0.0,0.0};
    static GLfloat normals[3];
    static GLfloat viewer[]= {0.0, 0.0, 10.0}; /* initial viewer location */
    static GLdouble x[4000000], y[4000000], f[4000000];
    static int n=0;
    static int inr[4000000];
     
    int inner (GLfloat v1[], GLfloat v2[]) {
     
      GLfloat p = 0.0;
      for (int i=0; i<3; i++)
        p += v1[i]*v2[i];
      if (p<0)
        return -1;
      else if (p>0)
        return 1;
      else
        return 0;
    }
     
    void init(void)
    {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
     
     n = 0;
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    /*x*/y[n] = t*(u*u - t*t);
    	    /*y*/x[n] = u;
    	    /*f*/f[n] = u*u - t*t;
    	  //x^2 - y^2 * Z^2 + Z^3 = 0
    	  normals[0] = 2.0 * x[n];
    	  normals[1] = -2.0 * y[n] * f[n] * f[n];
    	  normals[2] = -2.0 * y[n] * y[n] * f[n] + 3.0 * f[n] * f[n];
    	  GLfloat ray[3];
    	  ray[0] = x[n];
    	  ray[1] = y[n];
    	  ray[2] = f[n];
    	  inr[n++] = inner(ray, normals);
    	  }
    	}
    glEnable(GL_DEPTH_TEST);
    }
     
    void surface()
    {
    	glBegin(GL_POINTS);
    	for (int i=0; i<n; i++) {
    	  if (inr[i]>=0)
    	    glColor3f((x[i]+1)*0.25, (y[i]+1)*0.25, (f[i]+1)*0.25);
    	  else
    	    glColor3f((x[i]+3)*0.25, (y[i]+3)*0.25, (f[i]+3)*0.25);
    	  glVertex3d(x[i], y[i], f[i]);
    	}
    	glEnd();
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	glLoadIdentity();
     
    /* rotate surface */
     
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
    	glRotatef(theta[2], 0.0, 0.0, 1.0);
    surface();
    /* Use a perspective view */
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'X':theta[0]+=1;
    	  if (theta[0]==360) theta[0]=0;
    	  break;
    	case 'x': theta[0]-=1;
    	  if (theta[0]<0) theta[0] = 359;
    	  break;
    	case 'Y':theta[1]+=1;
    	  if (theta[1]==360) theta[1]=0;
    	  break;
    	case 'y': theta[1]-=1;
    	  if (theta[1]<0) theta[1] = 359;
    	  break;
    	case 'Z':theta[2]+=1;
    	  if (theta[2]==360) theta[2]=0;
    	  break;
    	case 'z': theta[2]-=1;
    	  if (theta[2]<0) theta[2] = 359;
    	  break;
    	}
    	glutPostRedisplay ();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    	}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
     
    	glutPostRedisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) 
    glOrtho(-2.4, 2.4, -2.4 * (GLfloat) h/ (GLfloat) w, 
    		   2.4* (GLfloat) h / (GLfloat) w, viewer[2]-1.8, viewer[2]+1.8);
    	else 
    glOrtho(-2.4* (GLfloat) w/ (GLfloat) h, 2.4* (GLfloat) w/ (GLfloat) h, -2.4,2.4, viewer[2]-1.8, viewer[2]+1.8);
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	init();
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glutKeyboardFunc(keyboard);
    	glutMainLoop();
    	return 0;
    }

  10. #10
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    19
    Quote Originally Posted by sueyllam View Post
    The code plots a surface with -1<=x<=1, -1<=y<=1< -1<=z<=1 in parametric form.
    It allows rotating to see the surface from different viewpoints... Of course this could generalize to any ranges. The only problem is the choice of colors of the surface, probably turning the displayed color into shades of gray would look better....

    Code :
    #include <math.h>
    #include <GL\glut.h>
     
    	GLint ww=500, wh=500;
    	int gbtn, gstate;
    static GLfloat theta[] = {0.0,0.0,0.0};
    static GLfloat normals[3];
    static GLfloat viewer[]= {0.0, 0.0, 10.0}; /* initial viewer location */
    static GLdouble x[4000000], y[4000000], f[4000000];
    static int n=0;
    static int inr[4000000];
     
    int inner (GLfloat v1[], GLfloat v2[]) {
     
      GLfloat p = 0.0;
      for (int i=0; i<3; i++)
        p += v1[i]*v2[i];
      if (p<0)
        return -1;
      else if (p>0)
        return 1;
      else
        return 0;
    }
     
    void init(void)
    {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
     
     n = 0;
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    /*x*/y[n] = t*(u*u - t*t);
    	    /*y*/x[n] = u;
    	    /*f*/f[n] = u*u - t*t;
    	  //x^2 - y^2 * Z^2 + Z^3 = 0
    	  normals[0] = 2.0 * x[n];
    	  normals[1] = -2.0 * y[n] * f[n] * f[n];
    	  normals[2] = -2.0 * y[n] * y[n] * f[n] + 3.0 * f[n] * f[n];
    	  GLfloat ray[3];
    	  ray[0] = x[n];
    	  ray[1] = y[n];
    	  ray[2] = f[n];
    	  inr[n++] = inner(ray, normals);
    	  }
    	}
    glEnable(GL_DEPTH_TEST);
    }
     
    void surface()
    {
    	glBegin(GL_POINTS);
    	for (int i=0; i<n; i++) {
    	  if (inr[i]>=0)
    	    glColor3f((x[i]+1)*0.25, (y[i]+1)*0.25, (f[i]+1)*0.25);
    	  else
    	    glColor3f((x[i]+3)*0.25, (y[i]+3)*0.25, (f[i]+3)*0.25);
    	  glVertex3d(x[i], y[i], f[i]);
    	}
    	glEnd();
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	glLoadIdentity();
     
    /* rotate surface */
     
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
    	glRotatef(theta[2], 0.0, 0.0, 1.0);
    surface();
    /* Use a perspective view */
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'X':theta[0]+=1;
    	  if (theta[0]==360) theta[0]=0;
    	  break;
    	case 'x': theta[0]-=1;
    	  if (theta[0]<0) theta[0] = 359;
    	  break;
    	case 'Y':theta[1]+=1;
    	  if (theta[1]==360) theta[1]=0;
    	  break;
    	case 'y': theta[1]-=1;
    	  if (theta[1]<0) theta[1] = 359;
    	  break;
    	case 'Z':theta[2]+=1;
    	  if (theta[2]==360) theta[2]=0;
    	  break;
    	case 'z': theta[2]-=1;
    	  if (theta[2]<0) theta[2] = 359;
    	  break;
    	}
    	glutPostRedisplay ();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    	}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
     
    	glutPostRedisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) 
    glOrtho(-2.4, 2.4, -2.4 * (GLfloat) h/ (GLfloat) w, 
    		   2.4* (GLfloat) h / (GLfloat) w, viewer[2]-1.8, viewer[2]+1.8);
    	else 
    glOrtho(-2.4* (GLfloat) w/ (GLfloat) h, 2.4* (GLfloat) w/ (GLfloat) h, -2.4,2.4, viewer[2]-1.8, viewer[2]+1.8);
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	init();
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glutKeyboardFunc(keyboard);
    	glutMainLoop();
    	return 0;
    }
    The colors get much better if you keep track of the ModelView matrix and compute the normal and ray according to it and not have them fixed according to original position.
    Here the code that does that:
    Code :
    #include <math.h>
    #include <GL\glut.h>
     
    	GLint ww=500, wh=500;
    	int gbtn, gstate;
    static GLfloat theta[] = {0.0,0.0,0.0};
    static GLfloat normals[4];
    static GLfloat viewer[]= {0.0, 0.0, 10.0}; /* initial viewer location */
    static GLdouble x[4000000], y[4000000], f[4000000];
    static GLdouble mv[4][4];
    static GLdouble trns[4][4]={{1.0,0.0,0.0,0.0},{0.0,1.0,0.0,0.0},{0.0,0.0,1.0,0.0},{0.0,0.0,0.0,1.0}};
    static GLdouble rtx[4][4]={{1.0,0.0,0.0,0.0},{0.0,1.0,0.0,0.0},{0.0,0.0,1.0,0.0},{0.0,0.0,0.0,1.0}};
    static GLdouble rty[4][4]={{1.0,0.0,0.0,0.0},{0.0,1.0,0.0,0.0},{0.0,0.0,1.0,0.0},{0.0,0.0,0.0,1.0}};
    static GLdouble rtz[4][4]={{1.0,0.0,0.0,0.0},{0.0,1.0,0.0,0.0},{0.0,0.0,1.0,0.0},{0.0,0.0,0.0,1.0}};
     
    //static GLdouble ac[4000000];
    static int n=0;
     
    void matmult (GLdouble m1[][4], GLdouble m2[][4], GLdouble m[][4]) {
      GLdouble t=0.0;
      for (int i=0; i<4; i++) {
        for (int j=0; j<4; j++) {
        t =0.0;
          for (int k=0; k<4; k++) {
    	t += m1[i][k]*m2[k][j];
          }
          m[i][j] = t;
        }
      }
    }
    int inner (GLfloat v1[], GLfloat v2[]) {
     
      GLfloat p = 0.0;
      for (int i=0; i<3; i++)
        p += v1[i]*v2[i];
      if (p<0)
        return -1;
      else if (p>0)
        return 1;
      else
        return 0;
    }
     
    void init(void)
    {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
     
     n = 0;
    	for (GLdouble u=-1.0; u<=1.0; u+=0.001) {
    	  for (GLdouble t=-1.0; t<=1.0; t+=0.001) {
    	    /*x*/y[n] = t*(u*u - t*t);
    	    /*y*/x[n] = u;
    	    /*f*/f[n++] = u*u - t*t;
    	  //	  ac[n] = (x[n]+y[n]+f[n])/3.0;
    	  }
    	}
    glEnable(GL_DEPTH_TEST);
    }
     
    void transform (GLfloat v[]) {
      GLdouble t[4]={0.0, 0.0, 0.0, 0.0};
      for (int i=0; i<4; i++) {
        for (int j=0; j<4; j++) {
          t[i] += mv[i][j]*v[j];
        }
      }
      for (int i=0; i<4; i++) {
        v[i] = t[i];
      }
    }
     
    void surface()
    {
    	glBegin(GL_POINTS);
    	for (int i=0; i<n; i++) {
    	  //GLfloat c1 = (ac[n] + 1.0)*0.25;
    	  //GLfloat c2 = (ac[n] + 3.0)*0.25;
    	  GLfloat ray[4];
    	  ray[0] = x[i];
    	  ray[1] = y[i];
    	  ray[2] = f[i];
    	  ray[3] = 1.0;
    	  //x^2 - y^2 * Z^2 + Z^3 = 0
    	  normals[0] = 2.0 * x[i];
    	  normals[1] = -2.0 * y[i] * f[i] * f[i];
    	  normals[2] = -2.0 * y[i] * y[i] * f[i] + 3.0 * f[i] * f[i];
    	  normals[3] = 1.0;
    	  transform (ray);
    	  transform (normals);
    	  if (inner(ray, normals)>=0)
    	    glColor3f((x[i]+1)*0.25, (y[i]+1)*0.25, (f[i]+1)*0.25);
    	    //glColor3f(c1,c1,c1);
    	  else
    	    glColor3f((x[i]+3)*0.25, (y[i]+3)*0.25, (f[i]+3)*0.25);
    	  //glColor3f(c2,c2,c2);
    	  glVertex3d(x[i], y[i], f[i]);
    	}
    	glEnd();
    }
     
    void myDisplay(void) {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	glLoadIdentity();
     
    /* rotate surface */
    	GLdouble temp[4][4], temp1[4][4];
    	rtz[0][0] = rtz[1][1] = cos(theta[2]*3.14159265359/180.0);
    	rtz[1][0] = sin(theta[2]*3.14159265359/180.0);
    	rtz[0][1] = -rtz[1][0];
    	rtx[2][2] = rtx[1][1] = cos(theta[0]*3.14159265359/180.0);
    	rtx[2][1] = sin(theta[0]*3.14159265359/180.0);
    	rtx[1][2] = -rtx[2][1];
    	matmult(rtx, rtz, temp);
    	rty[2][2] = rtx[0][0] = cos(theta[1]*3.14159265359/180.0);
    	rty[0][2] = sin(theta[1]*3.14159265359/180.0);
    	rty[2][0] = -rty[0][2];
    	matmult(rty,temp, temp1);
    	trns[0][3] = -viewer[0];
    	trns[1][3] = -viewer[1];
    	trns[2][3] = -viewer[2];
    	matmult(trns, temp1, mv);
    	glTranslatef(-viewer[0],-viewer[1],-viewer[2]);
    	glRotatef(theta[1], 0.0, 1.0, 0.0);
    	glRotatef(theta[0], 1.0, 0.0, 0.0);
    	glRotatef(theta[2], 0.0, 0.0, 1.0);
    surface();
     
     glFlush();
    	glutSwapBuffers();
    }
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'X':theta[0]+=1;
    	  if (theta[0]==360) theta[0]=0;
    	  break;
    	case 'x': theta[0]-=1;
    	  if (theta[0]<0) theta[0] = 359;
    	  break;
    	case 'Y':theta[1]+=1;
    	  if (theta[1]==360) theta[1]=0;
    	  break;
    	case 'y': theta[1]-=1;
    	  if (theta[1]<0) theta[1] = 359;
    	  break;
    	case 'Z':theta[2]+=1;
    	  if (theta[2]==360) theta[2]=0;
    	  break;
    	case 'z': theta[2]-=1;
    	  if (theta[2]<0) theta[2] = 359;
    	  break;
    	}
    	glutPostRedisplay ();
    }
     
    void mouse(int x, int y)
    {
    	static int t=0, xp, yp;
    	if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_DOWN) {
    		if (t==0) {
    			xp=x;
    			yp=y;
    			t=1;
    			return;
    		}
    		else {
    			theta[0]+=(y-yp); while (theta[0]>=360) theta[0]-=360; while (theta[0]<0) theta[0]+=360;
    			theta[1]+=(x-xp); while (theta[1]>=360) theta[1]-=360; while (theta[1]<0) theta[1]+=360;
    			xp=x;
    			yp=y;
    	}
    	}
    	else if(gbtn==GLUT_LEFT_BUTTON && gstate == GLUT_UP) {
    		t = 0;
    		return;
    	}
     
    	glutPostRedisplay();
    }
     
    void mouseClick(int btn, int state, int x, int y){
     
    	gbtn=btn;
    	gstate=state;
    	mouse(x,y);
    }
     
    void myReshape(int w, int h)
    {
     glViewport(0, 0, w, h);
    	ww=w;wh=h;
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity();
    	if(w<=h) 
    glOrtho(-2.4, 2.4, -2.4 * (GLfloat) h/ (GLfloat) w, 
    		   2.4* (GLfloat) h / (GLfloat) w, viewer[2]-1.8, viewer[2]+1.8);
    	else 
    glOrtho(-1.8* (GLfloat) w/ (GLfloat) h, 1.8* (GLfloat) w/ (GLfloat) h, -1.8, 1.8, viewer[2]-1.8, viewer[2]+1.8);
     
     glMatrixMode(GL_MODELVIEW);
    }
     
    int main(int argc, char** argv) {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    	glutInitWindowSize(ww,wh);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("3D Function Plot");
    	init();
    	glutReshapeFunc(myReshape);
    	glutDisplayFunc(myDisplay);
    	glutMotionFunc(mouse);
    	glutMouseFunc(mouseClick);
    	glutKeyboardFunc(keyboard);
    	glutMainLoop();
    	return 0;
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •