using glNormalPointer

hello,I’m new to this forum and in openGL. I use GLUT since i’m a beginner.I have a doubt in glNormalPointer.Here it is: well, we specify an array of normals and specify it in this function, but do the normals change when the model transform?

In my program I calculated the normal for each face individually and stored them in an array totally and then gave this total normals to the the funtion glNormalPointer.

I did this because i don’t know whether the normals change. Also I have used ModelView matrix to rotate the model.

When I compile the program, i get an error saying “unhandled exception in filename.exe”.

What is the error? and is my hunch correct?

Hi !

You can rotate and translate your object any way you want without having to change the normal vectors you have set, this is all taken care of for you by OpenGL.

Mikael

hi,

i thought that it was up to you to calculate all the normals of the models you specify. GLUT only calculates normals for the primitives it has, for example glutSolidCube or GlutSolidSphere.

heres a link that says it
http://users.frii.com/martz/oglfaq/lights.htm#ligh0030

oops and one more thing, i read from that link that the normals indeed change and the new normals have to appled. the problem is i’m taking the vertex information of a model from a waverfront .obj file. So there is a huge number of vertices.

The question is how do i apply the normals for each face? I have the functions to calculate but to call them for each face is too much…

can someone suggest what i should do? To try it out on a smaller model, i made a pyramid and used vertex arrays and also calculated all the normals for each face and supplied them to “glNormalPointer()”. but I get an execption handle error.

If you want the code, i’d post it.

Please help.

Hi

When you build your object, you have to specify the normals, as this is part of the model definition, along with the vertex data, etc. However, you don’t need to re-enter any normals after that, in the same way you don’t re-enter any vertex data. You don’t need to transform this data every time your object moves, OpenGL will do this for you, assuming you tell it so via model view transform.

It sounds to me that the crash you’re getting is caused by some problem in your code that creates the data you pass into glNormalPointer. I’d suggest you make sure you’ve filled the arrays in with valid data and double check you’re calling glNormalPointer correctly.

Good luck

mad

madmortigan, thanks. My doubts are slowly fading away. But my main problem is that I already have a the vertex positions taken from the wavefront .OBJ file. I’ll try to write a program to read from the file 3 vertex each and calculate the normal. But in the meanwhile i’m not able to clear this error from the prg. please help. the below is the code.

static float xRot,yRot;

static int x=0;

static float all_normals[12],bottom_normals[3],back_normals[3],lside_normals[3],front_normals[3];

void setupRC()
{

GLfloat ambient[] = {0.3f,0.3f,0.3f,1.0f};
GLfloat diffuse[] = {0.7f,0.7f,0.7f,0.0f};
GLfloat specular[]= {1.0f,1.0f,1.0f,1.0f};
GLfloat specRef[] = {1.0f,1.0f,1.0f,1.0f};
GLfloat	lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };

glEnable(GL_LIGHTING);

glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);

glEnable(GL_COLOR_MATERIAL);

glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

glMaterialfv(GL_FRONT,GL_SPECULAR,specRef);;
glMateriali(GL_FRONT,GL_SHININESS,128);


glShadeModel(GL_SMOOTH);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
	
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluPerspective(60.0f,1.0f,80.0f,40.0f);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluLookAt(0.0f,0.0f,80.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);

glClearColor(0.0f,0.0f,0.0f,1.0f);

}

void calcUnitNormals(float out[3])
{
float length;

length = (float)sqrt((out[0]*out[0]) + (out[1]*out[1]) + (out[2]*out[2]));

if(length==0.0f)
	length=1.0f;

out[0] /= length;
out[1] /= length;
out[2] /= length;

//printf("norm0: %f 

norm1: %f
norm2: %f
",out[0],out[1],out[2]);
}

void calcNormals(GLfloat v[3][3],GLfloat out[3])
{

GLfloat v1[3],v2[3];
static const int x=0,y=1,z=2;

v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];

v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];

out[x] = v1[y]*v2[z] - v2[y]*v1[z];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];

calcUnitNormals(out);

}

void specialKeys(int key,int x,int y)
{
if(key==GLUT_KEY_UP)
xRot +=5.0f;

if(key==GLUT_KEY_DOWN)
	xRot -= 5.0f;

if(key==GLUT_KEY_RIGHT)
	yRot += 5.0f;

if(key==GLUT_KEY_LEFT)
	yRot -= 5.0f;

if(key<0.0f)
	xRot=359.0f;

if(key>359.0f)
	xRot=0.0f;

if(key>359.0f)
	yRot=0.0f;

if(key<0.0f)
	yRot=359.0f;

glutPostRedisplay();

}

void combineNormals(float xNormal[])
{

	for(int i=0;i<=2;i++)
	{
		all_normals[x] = xNormal[i];
		x=x+1;
	}

}

void renderScene()
{

GLfloat pyramid_vertices[][3] = {{20.0f,0.0f,0.0f},
{0.0f,0.0f,60.0f},
{-20.0f,0.0f,0.0f},

{20.0f,0.0f,0.0f},
{-20.0f,0.0f,0.0f},
{0.0f,40.0f,30.0f},

{-20.0f,0.0f,0.0f},
{0.0f,0.0f,60.0f},
{0.0f,40.0f,30.0f},

{0.0f,0.0f,60.0f},
{20.0f,0.0f,0.0f},
{0.0f,40.0f,30.0f}};

//vertices for each face
float bottom_vertices[][3] = { 20.0f,0.0f,0.0f , 0.0f,0.0f,60.0f , -20.0f,0.0f,0.0f};

float back_vertices[][3] = {20.0f,0.0f,0.0f , -20.0f,0.0f,0.0f , 0.0f,40.0f,30.0f};

float lside_vertices[][3] = {-20.0f,0.0f,0.0f , 0.0f,0.0f,60.0f , 0.0f,40.0f,30.0f};

float front_vertices[][3] = {0.0f,0.0f,60.0f , 20.0f,0.0f,0.0f , 0.0f,40.0f,30.0f};


calcNormals(bottom_vertices,bottom_normals);
calcNormals(back_vertices,back_normals);
calcNormals(lside_vertices,lside_normals);
calcNormals(front_vertices,front_normals);

combineNormals(bottom_normals);;
combineNormals(back_normals);
combineNormals(lside_normals);
combineNormals(front_normals);

int k;
for(k=0;k<=12;k++)
	printf("%f

",all_normals[k]);

static GLubyte bottom[]={0,1,2};
static GLubyte back[]={3,4,5};
static GLubyte lside[]={6,7,8};
static GLubyte front[]={9,10,11};

static GLubyte allindices[]={0,1,2,3,4,5,6,7,8,9,10,11};

//color for the vertices
GLfloat pyramid_vertex_colors[][3] = {{1.0f,0.0f,0.0f},
{0.0f,1.0f,0.0f},
{0.0f,0.0f,1.0f},

{1.0f,1.0f,0.0f},
{1.0f,0.0f,1.0f},
{0.0f,1.0f,1.0f},

{0.25f,0.25f,0.25f},
{0.75f,0.75f,0.75f},
{0.60f,0.40f,0.12f},

{0.98f,0.625f,0.12f},
{0.98f,0.04f,0.7f},
{0.60f,0.40f,0.70f}};


glPushMatrix();
glRotatef(xRot,1.0f,0.0f,0.0f);
glRotatef(yRot,0.0f,1.0f,0.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3,GL_FLOAT,0,pyramid_vertex_colors);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT,0,all_normals);


glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,0,pyramid_vertices);

glDrawElements(GL_TRIANGLES,12,GL_UNSIGNED_BYTE,allindices);


glPopMatrix();

glutSwapBuffers();

}

void changeSize(GLsizei w, GLsizei h)
{
glViewport(0,0,w,h);

if(h==0)
	h=1;

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glOrtho(-30.0f,30.0f,-10.0f,60.0f,-100.0f,100.0f);
//gluPerspective(60.0f,1.0f,80.0f,40.0f);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

//gluLookAt(0.0f,0.0f,80.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);

}

void main()
{
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(“Hello”);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutSpecialFunc(specialKeys);
setupRC();

glutMainLoop();

}

Hi

I had a quick look at your code, without compiling it though. May be you’d like to reconsiderhow you’re using your pyramid_vertices and pyramid_vertices_colors arrays. You are creating them in the scope of renderscene function and passing the pointers to the pointer functions. This doesn’t seem very robust. May be you could try allocating these array dynamically (and deleting them before exiting your program), or stick them outside that function, like you did with the normals array.

I didn’t go through the normals calc code, I think you better address the crash first.

mad

for(k=0;k<=12;k++)

<= is wrong. You’re iterating 13 normals of an all_normals[12] array.

hello everyone, thanks for your reply.

I did what you all suggested but there wasn’t any change.

I’ll quickly tell you the overview of the program - firstly in the setupRC() callback i have done all the state enabling of GL and material and lighting creation and properties. In renderScene() which is used for display callback, i use vertex arrays for vertex definition and normal definition. So in order to get the all normal in an array, I have individually calculated the normals for each face and then combined them into a single array using the user defined combineNormals(). The error i get is not compile or linking error but a runtime error.The window shows the pyramid and when I try to rotate , i see changes in the shade a little bit and then i get an error saying :

unhandled exception in filname.exe 0x0000005 access violation.

I have been trying to correct this for two days without sleep.I don’t understand why this error occurs. I get 0 error and warning in the compile time.

I would be grateful to anyone who could compile this and tell me the mistake I made.

The code is given below after made the corrections i made from the first one.

Also can any one direct me to a working example of usage of glNormalPointer() program…

thanx. Please help.

#include<windows.h>
#include<GL/glut.h>
#include<math.h>
#include<stdio.h>

static float xRot,yRot;

static int x=0;

static float all_normals[12],bottom_normals[3],back_normals[3],lside_normals[3],front_normals[3];

GLfloat pyramid_vertices[][3] = {{20.0f,0.0f,0.0f},
{0.0f,0.0f,60.0f},
{-20.0f,0.0f,0.0f},

{20.0f,0.0f,0.0f},
{-20.0f,0.0f,0.0f},
{0.0f,40.0f,30.0f},

{-20.0f,0.0f,0.0f},
{0.0f,0.0f,60.0f},
{0.0f,40.0f,30.0f},

{0.0f,0.0f,60.0f},
{20.0f,0.0f,0.0f},
{0.0f,40.0f,30.0f}};


//vertices for each face

float bottom_vertices[][3] = { 20.0f,0.0f,0.0f , 0.0f,0.0f,60.0f , -20.0f,0.0f,0.0f};

float back_vertices[][3] = {20.0f,0.0f,0.0f , -20.0f,0.0f,0.0f , 0.0f,40.0f,30.0f};

float lside_vertices[][3] = {-20.0f,0.0f,0.0f , 0.0f,0.0f,60.0f , 0.0f,40.0f,30.0f};

float front_vertices[][3] = {0.0f,0.0f,60.0f , 20.0f,0.0f,0.0f , 0.0f,40.0f,30.0f};

static GLubyte bottom[]={0,1,2};
static GLubyte back[]={3,4,5};
static GLubyte lside[]={6,7,8};
static GLubyte front[]={9,10,11};

static GLubyte allindices[]={0,1,2,3,4,5,6,7,8,9,10,11};

//color for the vertices
GLfloat pyramid_vertex_colors[][3] = {{1.0f,0.0f,0.0f},
{0.0f,1.0f,0.0f},
{0.0f,0.0f,1.0f},

{1.0f,1.0f,0.0f},
{1.0f,0.0f,1.0f},
{0.0f,1.0f,1.0f},

{0.25f,0.25f,0.25f},
{0.75f,0.75f,0.75f},
{0.60f,0.40f,0.12f},

{0.98f,0.625f,0.12f},
{0.98f,0.04f,0.7f},
{0.60f,0.40f,0.70f}};

void setupRC()
{

GLfloat ambient[] = {0.3f,0.3f,0.3f,1.0f};
GLfloat diffuse[] = {0.7f,0.7f,0.7f,0.0f};
GLfloat specular[]= {1.0f,1.0f,1.0f,1.0f};
GLfloat specRef[] = {1.0f,1.0f,1.0f,1.0f};
GLfloat	lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };

glEnable(GL_LIGHTING);

glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);

glEnable(GL_COLOR_MATERIAL);

glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

glMaterialfv(GL_FRONT,GL_SPECULAR,specRef);;
glMateriali(GL_FRONT,GL_SHININESS,128);


glShadeModel(GL_SMOOTH);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
	
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluPerspective(60.0f,1.0f,80.0f,40.0f);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluLookAt(0.0f,0.0f,80.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);

glClearColor(0.0f,0.0f,0.0f,1.0f);

}

void calcUnitNormals(float out[3])
{
float length;

length = (float)sqrt((out[0]*out[0]) + (out[1]*out[1]) + (out[2]*out[2]));

if(length==0.0f)
	length=1.0f;

out[0] /= length;
out[1] /= length;
out[2] /= length;

//printf("norm0: %f 

norm1: %f
norm2: %f
",out[0],out[1],out[2]);
}

void calcNormals(GLfloat v[3][3],GLfloat out[3])
{

GLfloat v1[3],v2[3];
static const int x=0,y=1,z=2;

v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];

v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];

out[x] = v1[y]*v2[z] - v2[y]*v1[z];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];

calcUnitNormals(out);

}

void specialKeys(int key,int x,int y)
{
if(key==GLUT_KEY_UP)
xRot +=5.0f;

if(key==GLUT_KEY_DOWN)
	xRot -= 5.0f;

if(key==GLUT_KEY_RIGHT)
	yRot += 5.0f;

if(key==GLUT_KEY_LEFT)
	yRot -= 5.0f;

if(key&lt;0.0f)
	xRot=359.0f;

if(key&gt;359.0f)
	xRot=0.0f;

if(key&gt;359.0f)
	yRot=0.0f;

if(key&lt;0.0f)
	yRot=359.0f;

glutPostRedisplay();

}

void combineNormals(float xNormal[])
{

	for(int i=0;i&lt;=2;i++)
	{
		//checking contents of all_normals[i] and index x
		/*for(int s=0;s&lt;=2;s++)
		{printf("%f %d 

",all_normals[s], s);}*/
all_normals[x] = xNormal[i];
x=x+1;
}

}

void renderScene()
{

calcNormals(bottom_vertices,bottom_normals);
calcNormals(back_vertices,back_normals);
calcNormals(lside_vertices,lside_normals);
calcNormals(front_vertices,front_normals);

combineNormals(bottom_normals);;
combineNormals(back_normals);
combineNormals(lside_normals);
combineNormals(front_normals);


// just checking contents of all_normals[]
/*int k;
for(k=0;k&lt;=11;k++)
	printf("%f

",all_normals[k]);*/

glPushMatrix();
glRotatef(xRot,1.0f,0.0f,0.0f);
glRotatef(yRot,0.0f,1.0f,0.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3,GL_FLOAT,0,pyramid_vertex_colors);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT,0,all_normals);


glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,0,pyramid_vertices);

glDrawElements(GL_TRIANGLES,12,GL_UNSIGNED_BYTE,allindices);


glPopMatrix();

glutSwapBuffers();

}

void changeSize(GLsizei w, GLsizei h)
{
glViewport(0,0,w,h);

if(h==0)
	h=1;

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glOrtho(-30.0f,30.0f,-10.0f,60.0f,-100.0f,100.0f);
//gluPerspective(60.0f,1.0f,80.0f,40.0f);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

//gluLookAt(0.0f,0.0f,80.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);

}

void main()
{
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(“Hello”);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutSpecialFunc(specialKeys);
setupRC();

glutMainLoop();

}

It seems to me that your problem lies in
here
void combineNormals(float xNormal[])
{
for(int i=0;i<=2;i++)
{
//checking contents of all_normals[i] and index x
/for(int s=0;s<=2;s++)
{printf("%f %d
",all_normals[s], s);}
/
all_normals[x] = xNormal[i];
x=x+1; this looks like problem
}
}
because you are using the static variable in every renderscene you increase it by 12 but you are not setting it nowhere back to 0

duh , I see now. thanx a million vlasko. This is what i did -

void combineNormals(float xNormal[])
{
for(int i=0;i<=2;i++)
{
all_normals[x] = xNormal[i];
x=x+1;
//to set the index to 0 when renderScene display func is called next time
if(x==12)
x=0;
}
}

Well the system did not crash this time , but the normals did not work.I mean the pyramid was not lit. I traversed thru the program but found no error. Could any one see any error. This is baffling. By the way, the routine glNormalPointer is supposed work with glDrawElement ,isn’t it?

Please help. I think the normals calculated are not applied to the pyramid and hence no lighting. So how then is is to be applied to the model???

thanx