Why CallBack Functions are not called ?

Started by
4 comments, last by n9ine 15 years, 8 months ago
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[v][0] = 2.0*((GLfloat)u - 1.5);
			ctlpoints[v][1] = 2.0*((GLfloat)v - 1.5);

			if ( (u == 1 || u == 2) && (v == 1 || v == 2))
				ctlpoints[v][2] = 3.0;
			else
				ctlpoints[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]
Advertisement
Point the first: never cast function pointers.

Point the second: names starting with an underscore and an uppercase letter are reserved for the compiler (as are names beginning with two underscores).
This is why.

EDIT: Bah, too slow [smile]
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)

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#endifGLfloat 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[v][0] = 2.0*((GLfloat)u - 1.5);			ctlpoints[v][1] = 2.0*((GLfloat)v - 1.5);			if ( (u == 1 || u == 2) && (v == 1 || v == 2))				ctlpoints[v][2] = 3.0;			else				ctlpoints[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; }
the above code is working fine for me :)

What I have done is recompiling the glu lib (as a static library) and use it.

Hope this helps others.

This topic is closed to new replies.

Advertisement