Jump to content
  • Advertisement
Sign in to follow this  
lejno

OpenGL Cannot put OpenGL calls in a function

This topic is 3763 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I am playing around with OpenGL a bit this summer and it is great fun. However, I recently ran into a strange problem when writing a program to tryout display lists: I wrote a function, sine_surface(...), which renders a surface shaped like a sine wave, and used this function to generate a display list (see the code, below). It worked as intended. However, playing around with the code a bit I decided to call sine_surface(...) directly from my 'display'-function, without using a display list. When I did this, the surface disappeared. For this reason I tried a third option: pasting the code of sine_surface(...) directly into the 'display'-function, verbatim. This worked fine. What is going on here? I tried making a function, test(), which just rendered a single triangle. I was able to call test() successfully from my 'display'-function. So on the one hand, I can call some functions which render something, suggesting that my sine_surface(...) function is incorrect. On the other hand, when I paste the code from sine_surface() instead of calling it as a function, it works. In the code below, I have indicated code blocks to comment/uncomment if you want to try any of the options I described. I'm sure you will see what I mean. Here is the code: displists.c:
#include <GL/glut.h>

float cam_x = 0.0f; float cam_y = 0.0f; float cam_z = -5.0f; // Camera position
float time = 0.0f;

GLuint displist;

void display(void)
{
	time += 0.01f;

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(	cam_x, cam_y, cam_z,
				0.0, 0.0, 0.0,
				0.0, 1.0, 0.0	);

	// The floor
	glBegin(GL_QUADS);
		glColor3f(0.3, 0.6, 0.7);
		glVertex3f(+2.0f, -1.0f, -2.0f); glVertex3f(-2.0f, -1.0f, -2.0f);
		glVertex3f(-2.0f, -1.0f, +2.0f); glVertex3f(+2.0f, -1.0f, +2.0f);
	glEnd();

	// Basis vectors
	glBegin(GL_LINES);
		glColor3f(1.0, 0.0, 0.0); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.5f, 0.0f, 0.0f); // x-axis
		glColor3f(0.0, 1.0, 0.0); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.5f, 0.0f); // y-axis
		glColor3f(0.0, 0.0, 1.0); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.5f); // z-axis
	glEnd();

	glTranslatef(0.0f, 0.0f, sinf(time)); glScalef(0.5f, 0.5f, 0.5f); glRotatef(50.0f*time, 0.0f, 1.0f, 0.0f);
	glColor3f(1.0f, 1.0f, 0.0f);

	// Option 1: Call the displaylist (works)
	// glCallList(displist);

	// Option 2: Calling sine_surface (does not work)
	sine_surface(10, 50, 0.5f, 2.0f, 0.10f, 2.0f/4.0f, 3.14f);

	// Option 3: Paste the code from sine_surface (works)
	// ---sine_surface(10, 50, 0.5f, 2.0f, 0.10f, 2.0f/4.0f, 3.14f)------- //
	/*
	int nx = 10; int nz = 50;
	float lx = 0.5f; float lz = 2.0f;
	float ampl = 0.1f; float wlen = 2.0f/4.0f; float phase = 3.14f;

	float dx = lx / (float) nx; float dz = lz / (float) nz;
	float k = 2*3.1415f / wlen; // Wave number

	for(int i = 0; i < nz; ++i)
	{
		float z = -lz/2.0f + i*dz; float x = -lx/2.0f;
		glBegin(GL_TRIANGLE_STRIP);
		for(int j = 0; j <= nx; ++j)
		{
			glVertex3f(j*dx, ampl*sinf(k*(i*dz) + phase), i*dz);
			glVertex3f(j*dx, ampl*sinf(k*((i+1)*dz) + phase), (i+1)*dz);
		}
		glEnd();
	}
	*/
	// ------------------------------------------------------------------- //

	glFlush();
	glutPostRedisplay();
	glutSwapBuffers();
}

void test(void)
{
	glBegin(GL_TRIANGLES);
		glVertex3f(-0.25f, 0.25f, 0.0f); glVertex3f(+0.25f, 0.25f, 0.0f); glVertex3f(0.0f, -0.25f, 0.0f);
	glEnd();
}

void key(unsigned char key, int mx, int my)
{
	if		(key == 'w')	{ cam_y += 0.1f; }
	else if	(key == 's')	{ cam_y -= 0.1f; }
	else if	(key == 'a')	{ cam_x += 0.1f; }
	else if	(key == 'd')	{ cam_x -= 0.1f; }
	else if	(key == 'g')	{ cam_z += 0.1f; }
	else if	(key == 'h')	{ cam_z -= 0.1f; }
}

void sine_surface(int nx, int nz, float lx, float lz, float ampl, float wlen, float phase)
{
	float dx = lx / (float) nx; float dz = lz / (float) nz;
	float k = 2*3.1415f / wlen; // Wave number

	for(int i = 0; i < nz; ++i)
	{
		float z = -lz/2.0f + i*dz; float x = -lx/2.0f;
		glBegin(GL_TRIANGLE_STRIP);
		for(int j = 0; j <= nx; ++j)
		{
			glVertex3f(j*dx, ampl*sinf(k*(i*dz) + phase), i*dz);
			glVertex3f(j*dx, ampl*sinf(k*((i+1)*dz) + phase), (i+1)*dz);
		}
		glEnd();
	}
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
	glutInitWindowSize(500, 500);
	int win = glutCreateWindow("displists");
	glutDisplayFunc(display);
	glutKeyboardFunc(key);

	glDisable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0f);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, 1.0f, 0.1f, 10.0f);

	displist = glGenLists(1);
	glNewList(displist, GL_COMPILE);
		sine_surface(10, 50, 0.5f, 2.0f, 0.10f, 2.0f/4.0f, 3.14f);
	glEndList();
	
	glutMainLoop();

	return 0;
}





Makefile:
GLLIBS = -lglut -lGLU -lGL
XLIBS = -lXi -lXmu -lX11 -lXext
MISCLIBS = -lm

LIBS = $(GLLIBS) $(XLIBS) $(MISCLIBS)

CC = gcc
CFLAGS = -g -Wall -std=c99

all : displists

displists : displists.o
	$(CC) $(CFLAGS) -o displists displists.o $(LIBS)

.c.o:		; $(CC) -c $(CFLAGS) $(IPATH) $<

clean:
	$(RM) *.o displists





Share this post


Link to post
Share on other sites
Advertisement
The only thing that looks suspicious to me is the lack of a function prototype for sine_surface before your display function's definition. Try adding that and see if it works for you.

Share this post


Link to post
Share on other sites
I moved sine_surface(...) to above display(...) and it worked!
Thanks a lot!
I cannot believe I didn't try that, I guess I am used to getting errors when I do something stupid like using a function before it is declared.

However, the function test() (which draws only a triangle) works fine wherever I put it... very strange.

Share this post


Link to post
Share on other sites
The reason why is that in C, if you do not make a prototype for a function, the compiler tries to figure out the argument types (this is fine for whay you ahve since you use f on you rfloat constants) and the compiler makes the return type an int. The function_test(), does not have issues because it takes no arguments, and so the stack does not get all messed up, but sine_function takes arguments, so there is stuff pushed on the stack, and the compiler thinks it returns an int, but it does not return anything, so the stack goes bad.

Share this post


Link to post
Share on other sites
Ok. Thanks for explaining that.
Once I learned what the solution was I figured it must be something like what you just said.
In hindsight I feel silly for posting this in the OpenGL forum.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!