Sign in to follow this  
n9ine

Why CallBack Functions are not called ?

Recommended Posts

Hi all; I am having a problem with this code. _My_beginCallback and others are not called. The code compiles succesfully and I can view the nurb but calls to callback are not succeded. As a result I obtained : Init Surface beginCallback vertexCallback normalCallback endCallback nurbsError
#include "windows.h"
#include "gl/gl.h"
#include "glu.h"
#include "glut.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"




#ifndef CALLBACK 
#define CALLBACK
#endif

GLfloat ctlpoints[4][4][3];
int showPoints = 0;
FILE  *fp;

GLUnurbsObj *theNurb;


/*
*
*  Initializes the control points of the surface to a small hill.
*  The control points range from -3 to +3 in x, y, and z
*/
void init_surface(void)
{
	printf("Init Surface\n");
	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  _My_nurbsError(GLenum errorCode)
{
	const GLubyte *estring;

	estring = gluErrorString(errorCode);
	fprintf (stderr, "Nurbs Error: %s\n", estring);
	exit (0);
}

void   _My_beginCallback(GLenum whichType)
{
	printf("INSIDE beginCallback\n");
	glBegin (whichType);  /*  resubmit rendering directive  */
	printf ("glBegin(");
	switch (whichType) {  /*  print diagnostic message  */
	  case GL_LINES:
		  printf ("GL_LINES)\n");
		  break;
	  case GL_LINE_LOOP:
		  printf ("GL_LINE_LOOP)\n");
		  break;
	  case GL_LINE_STRIP:
		  printf ("GL_LINE_STRIP)\n");
		  break;
	  case GL_TRIANGLES:
		  printf ("GL_TRIANGLES)\n");
		  break;
	  case GL_TRIANGLE_STRIP:
		  printf ("GL_TRIANGLE_STRIP)\n");
		  break;
	  case GL_TRIANGLE_FAN:
		  printf ("GL_TRIANGLE_FAN)\n");
		  break;
	  case GL_QUADS:
		  printf ("GL_QUADS)\n");
		  break;
	  case GL_QUAD_STRIP:
		  printf ("GL_QUAD_STRIP)\n");
		  break;
	  case GL_POLYGON:
		  printf ("GL_POLYGON)\n");
		  break;
	  default:
		  break;
	}
}

void    _My_endCallback()
{
	glEnd();  /*  resubmit rendering directive  */
	printf ("glEnd()\n");
}

void    _My_vertexCallback(GLfloat *vertex)
{
	printf("INSIDE vertexCallback\n");
	glVertex3fv(vertex);  /*  resubmit rendering directive  */
	fprintf (fp,"glVertex3f (%5.3f, %5.3f, %5.3f)\n", 
		vertex[0], vertex[1], vertex[2]);
}

void    _My_normalCallback(GLfloat *normal)
{
	glNormal3fv(normal);  /*  resubmit rendering directive  */
	fprintf (fp,"glNormal3f (%5.3f, %5.3f, %5.3f)\n", 
		normal[0], normal[1], normal[2]);
}
/*			
*  Initialize material property and depth buffer.
*/
void init(void)
{
	GLfloat mat_diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
	GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 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_NURBS_MODE, 
		GLU_NURBS_TESSELLATOR);
	gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 20.0);
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);



	gluNurbsCallback(theNurb, GLU_NURBS_BEGIN, (void (__stdcall *) ( )) &_My_beginCallback);
	printf("beginCallback\n");
	gluNurbsCallback(theNurb, GLU_NURBS_VERTEX,  (void (__stdcall *) ( )) &_My_vertexCallback);
	printf("vertexCallback\n");
	gluNurbsCallback(theNurb, GLU_NURBS_NORMAL,  (void (__stdcall *) ( )) &_My_normalCallback);
	printf("normalCallback\n");
	gluNurbsCallback(theNurb, GLU_NURBS_END,  (void (__stdcall *) ( )) &_My_endCallback);
	printf("endCallback\n");
	gluNurbsCallback(theNurb, GLU_ERROR,  (void (__stdcall *) ( )) &_My_nurbsError);
	printf("nurbsError\n");


}

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();
	glRotatef(330.0, 1.,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);

	glFlush();


}

void reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective (45.0, (GLdouble)w/(GLdouble)h, 3.0, 8.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef (0.0, 0.0, -5.0);
}

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;
	}
}

int main(int argc, char** argv)
{
	fp = fopen("data_for_vetex.txt","a");
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize (500, 500);
	glutInitWindowPosition (100, 100);
	glutCreateWindow(argv[0]);
	init();
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);
	glutKeyboardFunc (keyboard);

	glutMainLoop();
	return 0; 
}



[Edited by - n9ine on August 19, 2008 1:50:32 AM]

Share this post


Link to post
Share on other sites
First, remove the ampersand sign (&) in your GLU callback registration. The function name itself is acted as a pointer, as same as an array variable. For example:
gluNurbsCallback(theNurb, GLU_NURBS_BEGIN, (void (__stdcall *)())_My_beginCallback);




Second, you should have __stdcall calling convention in your function declaration/definition. for example:
void __stdcall _My_beginCallback(GLenum whichType)
{
...
}




I think it should fix your problem, but here is an extended explanation for better understanding.

When you look at the glu.h header file, GLU callback registration function requires _GLUfuncptr type for the callback function pointer:
GLAPI void APIENTRY gluNurbsCallback (GLUnurbs* nurb, GLenum which, _GLUfuncptr CallBackFunc);




Also, note that _GLUfuncptr is defined in glu.h:
typedef void (APIENTRY *_GLUfuncptr)();



It means the function pointer, _GLUfuncptr needs APIENTRY calling convention. And, APIENTRY is defined as __stdcall in Windows system, which means APIENTRY = __stdcall. Therefore, you need __stdcall in your callback registration and declaration.

The problem is that __stdcall is a Windows-specific keyword, so other OS cannot recognize this calling convention. You may make the code more portable by using additional keyword. Since you already have CALLBACK definition in the beginning of your code, you can replace __stdcall to CALLBACK. As a result, you can hide the Windows-specific keyword and the code is more portable.

#ifndef CALLBACK
#define CALLBACK
#endif
...
void CALLBACK _My_beginCallback(GLenum whichType)
{
...
}
...
void init()
{
...
gluNurbsCallback(theNurb, GLU_NURBS_BEGIN, (void (CALLBACK *)()) _My_beginCallback);
...
}
...




Note that CALLBACK is already defined as __stdcall in "windef.h". Therefore, CALLBACK will be automatically replaced to __stdcall in Windows system. But, other OS will ignore CALLBACK keyword and uses the default calling convention instead. (because you define CALLBACK with no value in your code)

Share this post


Link to post
Share on other sites

Thanks for help, I have made the changes you recommand but I still having the same problem.


#include "windows.h"
#include "gl/gl.h"
#include "glu.h"
#include "glut.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"




#ifndef CALLBACK
#define CALLBACK
#endif

GLfloat ctlpoints[4][4][3];
int showPoints = 0;
FILE *fp;

GLUnurbsObj *theNurb;


/*
*
* Initializes the control points of the surface to a small hill.
* The control points range from -3 to +3 in x, y, and z
*/

void init_surface(void)
{
printf("Init Surface\n");
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 __stdcall _My_nurbsError(GLenum errorCode)
{
const GLubyte *estring;

estring = gluErrorString(errorCode);
fprintf (stderr, "Nurbs Error: %s\n", estring);
exit (0);
}

void __stdcall _My_beginCallback(GLenum whichType)
{
printf("INSIDE beginCallback\n");
glBegin (whichType); /* resubmit rendering directive */
printf ("glBegin(");
switch (whichType) { /* print diagnostic message */
case GL_LINES:
printf ("GL_LINES)\n");
break;
case GL_LINE_LOOP:
printf ("GL_LINE_LOOP)\n");
break;
case GL_LINE_STRIP:
printf ("GL_LINE_STRIP)\n");
break;
case GL_TRIANGLES:
printf ("GL_TRIANGLES)\n");
break;
case GL_TRIANGLE_STRIP:
printf ("GL_TRIANGLE_STRIP)\n");
break;
case GL_TRIANGLE_FAN:
printf ("GL_TRIANGLE_FAN)\n");
break;
case GL_QUADS:
printf ("GL_QUADS)\n");
break;
case GL_QUAD_STRIP:
printf ("GL_QUAD_STRIP)\n");
break;
case GL_POLYGON:
printf ("GL_POLYGON)\n");
break;
default:
break;
}
}

void __stdcall _My_endCallback()
{
glEnd(); /* resubmit rendering directive */
printf ("glEnd()\n");
}

void __stdcall _My_vertexCallback(GLfloat *vertex)
{
printf("INSIDE vertexCallback\n");
glVertex3fv(vertex); /* resubmit rendering directive */
fprintf (fp,"glVertex3f (%5.3f, %5.3f, %5.3f)\n",
vertex[0], vertex[1], vertex[2]);
}

void __stdcall _My_normalCallback(GLfloat *normal)
{
glNormal3fv(normal); /* resubmit rendering directive */
fprintf (fp,"glNormal3f (%5.3f, %5.3f, %5.3f)\n",
normal[0], normal[1], normal[2]);
}
/*
* Initialize material property and depth buffer.
*/

void init(void)
{
GLfloat mat_diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 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_NURBS_MODE,
GLU_NURBS_TESSELLATOR);
gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 20.0);
gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);



gluNurbsCallback(theNurb, GLU_NURBS_BEGIN, (void (__stdcall *) ( )) _My_beginCallback);
printf("beginCallback\n");
gluNurbsCallback(theNurb, GLU_NURBS_VERTEX, (void (__stdcall *) ( )) _My_vertexCallback);
printf("vertexCallback\n");
gluNurbsCallback(theNurb, GLU_NURBS_NORMAL, (void (__stdcall *) ( )) _My_normalCallback);
printf("normalCallback\n");
gluNurbsCallback(theNurb, GLU_NURBS_END, (void (__stdcall *) ( )) _My_endCallback);
printf("endCallback\n");
gluNurbsCallback(theNurb, GLU_ERROR, (void (__stdcall *) ( )) _My_nurbsError);
printf("nurbsError\n");


}

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();
glRotatef(330.0, 1.,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);

glFlush();


}

void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (45.0, (GLdouble)w/(GLdouble)h, 3.0, 8.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef (0.0, 0.0, -5.0);
}

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;
}
}

int main(int argc, char** argv)
{
fp = fopen("data_for_vetex.txt","a");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc (keyboard);

glutMainLoop();
return 0;
}






Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this