NURBS and mouse handling

hello everyone

here is a program including drawing a NURBS object using the function and a routine to handle mouse. the problem is that in the reshape function, to draw a NURBS object perspective projection is required followed by translation. whereas for mouse handling routine, in order to draw small polygon where mouse is clicked, an ortho projection is required without translation. now, both r to put in reshape function, but only one of the 2 works at a time. so, i’ve commented the other one.

can anyone please help me in combining the 2 modules so that both work together.

here is the code:


#include<GL/glut.h>
#include<stdlib.h>
#include<stdio.h>

#ifndef CALLBACK
#define CALLBACK
#endif

GLsizei wh=300,ww=300;
GLfloat size=1.0;
GLfloat ctlpoints[4][4][3];
int showPoints=0;

GLUnurbsObj *theNurb;

/*
draw a polygon where mouse is clicked
*/
void drawSquare(int btn,int state,int x,int y)
{
if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
{
y=wh-y;
glColor3f(0.5,0.0,0.6);
glBegin(GL_POLYGON);
glVertex2f(x+size,y+size);
glVertex2f(x-size,y+size);
glVertex2f(x-size,y-size);
glVertex2f(x+size,y-size);
glEnd();
glFlush();
}

if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)
	exit(0);

}

/*
defining control points for a regular NURBS object
draws a semi sphere
/
void init_surface(void)
{
int u,v;
for (u = 0; u < 4; u++)
for (v = 0; v < 4; v++)
{ ctlpoints[u][v][0]=2.0
((GLfloat)u-1.5);
ctlpoints[u][v][1]=2.0*((GLfloat)v-1.5);
if((u==1 | | u==2) && (v==1 | | v==2))
ctlpoints[u][v][2]=3.0;
else
ctlpoints[u][v][2]=-3.0;
}
}

void CALLBACK nurbsError(GLenum errorCode)
{
const GLubyte *estring;
estring=gluErrorString(errorCode);
fprintf(stderr,"Nurbs Error: %s
",estring);
exit(0);
}

void reshape(int w, int h)
{
/*
to draw NURBS object
*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75.0,(GLdouble)w/(GLdouble)h,3.0,8.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,(GLsizei) w,(GLsizei) h);
glTranslatef(0.0,0.0,-5.0);
glViewport(0,0,w,h);
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();

/*
draw a small polygon at mouse click event
which i've commented out coz both do not work together
*/
/*
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,(GLdouble)w,0.0,(GLdouble)h,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,w,h);
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
*/

ww=w;
wh=h;

}

void init(void)
{
GLfloat mat_diffuse[]={0.7,0.7,0.7,1.0};
GLfloat mat_specular[]={0.4,0.0,0.6,1.0};
GLfloat mat_shininess[]={100.0};

glClearColor(0.0,0.0,0.0,0.0);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);

init_surface();

theNurb=gluNewNurbsRenderer();
gluNurbsProperty(theNurb,GLU_SAMPLING_TOLERANCE,25.0);
gluNurbsProperty(theNurb,GLU_DISPLAY_MODE,GLU_OUTLINE_POLYGON);
gluNurbsCallback(theNurb,GLU_ERROR,nurbsError);

}

/*
event to display the control points
*/
void keyboard(unsigned char key,int x ,int y)
{ switch(key)
{ case ‘c’:
case ‘C’:
showPoints=!showPoints;
glutPostRedisplay();
break;
case ‘27’:
exit(0);
break;
default:
break;
}
}

void display(void)
{
GLfloat knots[8]={0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0};
int i,j;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();
glTranslatef(0.0,2.0,0.0);
glRotatef(270.0,1.0,0.0,0.0);
glScalef(0.5,0.5,0.5);
gluBeginSurface(theNurb);
	gluNurbsSurface(theNurb,8,knots,8,knots,4*3,3,&ctlpoints[0][0][0],4,4,GL_MAP2_VERTEX_3);
gluEndSurface(theNurb);

/*
display the control points
*/
if(showPoints)
{ 
	glPointSize(5.0);
	glDisable(GL_LIGHTING);
	glColor3f(0.0,1.0,1.0);
	glBegin(GL_POINTS);
	for (i = 0; i &lt; 4; i++){
		for (j = 0; j &lt; 4; j++){
			glVertex3f(ctlpoints[i][j][0],ctlpoints[i][j][1],ctlpoints[i][j][2]);
		}
	}
	glEnd();
	glEnable(GL_LIGHTING);
}
glPopMatrix();
glFlush();

}

int main(int argc,char **argv)
{ glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(ww,wh);
glutInitWindowPosition(100,100);
glutCreateWindow(“NURBS”);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMouseFunc(drawSquare);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}


thanks a lot!
anxious

Why do you need glOrtho matrix?
You can simply map mouse coords into perspective mode.

Originally posted by RandyU:
Why do you need glOrtho matrix?
You can simply map mouse coords into perspective mode.

could u plz suggest apt values for the gluPerspective function so that both mouse click and NURBS work with it. i tried to play with those values but mous requires an ortho prohection.

When you say only one works at a time, what do you mean exactly? Only one displays at a time? You appear to be doing a glClear for both the nurbs and the polygon. If you want them both to display, you will have to do the glClear, then draw them both. I just took a quick look at the code but it appears you are doing

glClear
drawNurbs
glClear
drawPolygon

Originally posted by Deiussum:
[b]When you say only one works at a time, what do you mean exactly? Only one displays at a time? You appear to be doing a glClear for both the nurbs and the polygon. If you want them both to display, you will have to do the glClear, then draw them both. I just took a quick look at the code but it appears you are doing

glClear
drawNurbs
glClear
drawPolygon[/b]

well, there r three things happening here:

(1) showing polygon of size 1 at the mouse click event at their respective coordinates. this is done in drawSquare(…) func.

(2) there is a small piece of code at the end of the display func which i forgot to add earlier (sorrry for that). this is to display a bmp image on the output window. here r those few lines of code:

glLoadIdentity();//Reset The current Modelview Matrix
glTranslatef(0.0f,0.0f,-5.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_POLYGON);
glTexCoord2f(6.0f, 0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(6.0f, 6.0f);
glVertex3f(-1.0f,1.0f,-1.0f);
glTexCoord2f(0.0f, 6.0f);
glVertex3f(1.0f,1.0f,-1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
glEnd();
glFlush();
glDisable(GL_TEXTURE_2D);

(3) and the one to draw a NURBS object is written in init_surface() in the for loop.

  now, have a look at the reshape func, divided with the two comments.

 since displaying the bmp and NURBS object require perspective projection and displaying the polygon at mouse click requires ortho projection, only the one written earlier remains the active one, ie, either displaying bmp and NURBS or drawing polygon at mouse.

click func.

if mouse click part is to be activated, then the piect of code i've written above should not be there, and the reshape func should include the ortho projection(latter half which is commented there).

so, the conclusion is NURBS and loadbmp go hand in hand and mouse is left behind, and have to get the three together.

i hope i’ve made myself clear enough!! (though it still sounds confusing)

anywise, thanks in advance!

anxious

This is the part that I’m not quite understanding… I’ve added comments to the parts I don’t quite understand what you are trying to do.

// first of all, the reshape function gets called when the window is resized
// but you are talking about mouse events?
void reshape(int w, int h)
{
/*
to draw NURBS object
*/
// ok…
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75.0,(GLdouble)w/(GLdouble)h,3.0,8.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,(GLsizei) w,(GLsizei) h);
glTranslatef(0.0,0.0,-5.0);
glViewport(0,0,w,h);
// if your clear color doesn’t change, why set it every time here?
glClearColor(0.0,0.0,0.0,0.0);
// Clearing the color buffer once…
glClear(GL_COLOR_BUFFER_BIT);
// Why flush? Haven’t drawn anything yet
glFlush();

/*
draw a small polygon at mouse click event
which i’ve commented out coz both do not work together
/
/

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// You switched to a Perspective view, didn’t
// do anything but clear, and now you are switching
// to an Ortho view. I don’t get it…
glOrtho(0.0,(GLdouble)w,0.0,(GLdouble)h,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
// What was the point of the translate above?
// You didn’t draw anything, and now you are setting it back to the identity.
glLoadIdentity();
// You already set glViewport above? Why do it again here to the same thing?
glViewport(0,0,w,h);
// Setting the clear color a second time to the same thing? Redundant…
glClearColor(0.0,0.0,0.0,0.0);

// Why clear again? It’s already been cleared.
glClear(GL_COLOR_BUFFER_BIT);
// Another flush?
glFlush();
*/

ww=w;
wh=h;
}

It seems to me that you may be under the impression that OpenGL saves separate state info for both Projection and Ortho modes. This is not the case.

What I would do would be something like so…

// Pseudo-code
void Display()
{
glClear();
SetupProjection();
DrawNurbsObject();
SetupOrtho();
DrawMouseClickPolys();
glFlush();
}

void OnMouseClick(// yada yada)
{
AddPolyToListOfMouseClickPolys();
glutPostRedisplay();
}

[This message has been edited by Deiussum (edited 02-02-2001).]

(1) yes, u r right. it will get called when window is resized and i have to do that in order to note the changes.
(2) actually i was changing colors to different values initially, that is why its been put up there.
(3) ‘flush’ , well, i thought if anything could work ( i know it sounds stupid. but when u get frustrated, u tend to do stuff like this)
(4) only one of the portion written above the comment and below it is activated. that is why i’ve written it in both the places in the same function. otherwise it is required only once.

he ho !! ho he!!
thanks
u know i actually thought on what u said and did it. now i can do all draw NURBS object, load the bmp and get the mouse clicks on it.
can i obtain these coordinates now to store them as control points and interpolate a curve through these points (NURBS).
thanks a million!! :slight_smile:
anxious, less though

I actually haven’t done much with the GLU Nurbs stuff. I’ve done a little with the glMap1d stuff, though. Probably the easiest thing you could do would be to store your control points in an STL container like a vector. Then you could just use that data to rebuild the nurbs when you add new control points.