Jump to content
  • Advertisement
Sign in to follow this  
newbird

OpenGL Update Normals using the Matrix

This topic is 4772 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

Hi everyone, I have a simple problem I was hoping someone could help me with. I have a simple OpenGL program where I need to recompute the normals every frame to point toward the camera. I'm using the well-known ArcBall algorithm for rotating the OpenGL object using mouse input. In my display function I translate the object away from the origin such that I can see the entire object. I then rotate the object according to the 4x4 ArcBall matrix via: float* matrix=Spaceball.GetMatrix(); glMultMatrixf(matrix); Now for every point in my scene, I need to assign the x,y,z values of the new normal for that point (so that it continues to point toward the camera despite having been rotated). I'm sure it's a simple set of equations, but it currently escapes me on how to do this. Can anyone figure out how to assign the normals to point toward the camera by essentially using this modelview matrix? Below is my display function which attempts to use the inverse transpose of this matrix to find the new normal but it is obviously wrong and the actual solution may be simpler: void glutDisplay(void) { int i; unsigned short* pos; float SpaceballInvT[16]; float normalDir[4]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPushMatrix(); /* translate camera to the coordinates provided by eye array */ glTranslatef (-eye[0], -eye[1], -(eye[2]-zoom*eye[2])); glMultMatrixf(Spaceball.GetMatrix()); Spaceball.GetInvMatrix(SpaceballInvT); TransposeMatr(SpaceballInvT); Spaceball.Update(); //Update the normals for each voxel for(i=0;i<numVerts;i++) { pos = (unsigned short*)&voxels[i*10+4]; MatMult4f(normalDir, SpaceballInvT, (float)pos[0], (float)pos[1], (float)pos[2], 1.f); voxels[i*10+ 1] = (unsigned char)normalDir[0];// x-component of normal voxels[i*10+ 2] = (unsigned char)normalDir[1];// y-component of normal voxels[i*10+ 3] = (unsigned char)normalDir[2];// z-component of normal } glTranslated(-DIM_SIZE/2,-DIM_SIZE/2,-DIM_SIZE/2); VolrSsplats(voxels, numVerts, dimSize); //Draw hairy splats that show directions of the normal if(showNormals) { Disable_Splatting(); for(i=0;i<numVerts;i++) { glBegin(GL_LINES); pos = (unsigned short*)&voxels[i*10+4]; glVertex3f(pos[0],pos[1],pos[2]); glVertex3f(pos[0]+5.f*(float)voxels[i*10+1]/255.f,pos[1]+5.f*(float)voxels[i*10+2]/255.f,pos[2]+5.f*(float)voxels[i*10+3]/255.f); glEnd(); } Enable_Splatting(); } glPopMatrix(); glFlush(); glutSwapBuffers(); }

Share this post


Link to post
Share on other sites
Advertisement
It's the normalized negative of the vector position of that point minus the vector position of the camera.

new_normal = -(point_pos - camera_pos);
new_normal = Normalize(new_normal);

Oh, the points position has to be in worldspace. You get that by multipling the point by its transformation matrix.

Share this post


Link to post
Share on other sites
A good idea FlyingDemon, I had thought of trying that before. It seems simple and yet I'm having difficulty. I get the modelview matrix and multiply it by the original point to get the object space coordinate. However, if I try to calculate the vector from that point to the camera (commented as "insta non-render"), my screen shows up but it doesn't render anything...not even the black clear color. Perhaps you have another suggestion?

void glutDisplay(void)
{
int i;
unsigned short* pos;
float SpaceballInv[16];
float normalDir[4];

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glPushMatrix();

/* translate camera to the coordinates provided by eye array */
glTranslatef (-view.eye[0], -view.eye[1], -(view.eye[2]-view.zoom*view.eye[2]));
glMultMatrixf(Spaceball.GetMatrix());
Spaceball.Update();

glTranslated(-DIM_SIZE/2,-DIM_SIZE/2,-DIM_SIZE/2);
if(updateNormals) {
glGetFloatv (GL_MODELVIEW_MATRIX, SpaceballInv);
for(i=0;i<numVerts;i++) {
pos = (unsigned short*)&voxels[i*10+4];
MatMult4f(normalDir, SpaceballInv, (float)pos[0], (float)pos[1], (float)pos[2], 1.f);
for(j=0;j<3;j++) normalDir[j]=-1.f*(255.f*(float)pos[j] - view.eye[j]);
Normalize3(&normalDir[0]);

voxels[i*10+ 1] = (unsigned char)(255.f*normalDir[0]); // x-component of normal
voxels[i*10+ 2] = (unsigned char)(255.f*normalDir[1]); // y-component of normal
voxels[i*10+ 3] = (unsigned char)(255.f*normalDir[2]); // z-component of normal
}
}//End update normals

VolrSsplats(voxels, numVerts, dimSize);

glPopMatrix();
glFlush();
glutSwapBuffers();
}

[Edited by - newbird on June 25, 2005 2:17:05 PM]

Share this post


Link to post
Share on other sites
Make sure that your not multiplying your verts twice. You use glMultMatrix at first but later on you also multiply the verts again to get their new positions, i think.

A question...
What are you trying to do? - Have the object constantly lit on the side that points towards the camera?

Share this post


Link to post
Share on other sites
The glMultMatrix() call allows me to rotate the cubic volume that I have. The pos variable is referencing each voxel's location within that volume. The glMultMatrix simply allows me to move those points to the correct location based upon the ArcBall. Nothing changes the coordinates of each voxel within the volume as these are stored in voxels[i*10+ 4,5,6].

The second "MatMult4f(normalDir, SpaceballInvT, (float)pos[0], (float)pos[1], (float)pos[2], 1.f);" for each voxel simply allows me to store the OpenGL object-space coordinates for the current voxel. Given the current transformation matrix, the new object coordinates of each voxel should be stored in the normalDir vector.

Good question as to what precisely I want to do. Sometimes I leave out the essence. I have a headlight, so the light is positioned at the same place as the camera. So yes, the side facing the camera is always lit. I had hoped to get the normals correctly pointing toward the camera at all times and then adjust the light so that I get a white specular highlight in the middle of every splat (so they appear more round rather than blending together).

Share this post


Link to post
Share on other sites
"The second "MatMult4f(normalDir, SpaceballInvT, (float)pos[0], (float)pos[1], (float)pos[2], 1.f);" for each voxel simply allows me to store the OpenGL object-space coordinates for the current voxel. Given the current transformation matrix, the new object coordinates of each voxel should be stored in the normalDir vector."


MatMult4f(normalDir, SpaceballInv, (float)pos[0], (float)pos[1], (float)pos[2], 1.f);
/*//Insta-nonrender
for(i=0;i<3;i++) normalDir=-1.f*((float)pos - view.eye);

^^ You filled in the 'normalDir' using MatMult4f, then right after you gave them a different value? - Is that intended?

Share this post


Link to post
Share on other sites
No, that's not what is intended. Obviously I'm a moron. pos should be normalDir, since normalDir is the transformed location of pos. Even so, I still have the same behavior as far as the window not being rendered. Also, should I be using the MODELVIEW or the PROJECTION matrix? I appreciate your patience, feel free to tell me I'm a moron and move on with your life. ^_^

Share this post


Link to post
Share on other sites
Im out of ideas( i never has any) about why its not rendering, even the clear color. Comment the entire thing out peice by peice until it starts to render again, that should give an idea.

Share this post


Link to post
Share on other sites
It's certainly the for i<3 loop that causes the program not to render. I don't know why it'd cause that, I'll inspect the values and see if maybe they're odd values that might be confusing the OpenGL state machine.

Share this post


Link to post
Share on other sites
Well let this be a lesson to you then!

Only declare variables in the scopes in which they're used...

you're blowing away the value of i from the outter loop when you do i=0;i<3

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!