PDA

View Full Version : Scene "eaten by black hole"



TSorcerer
11-22-2008, 06:57 PM
Hi there,

I have a very strange bug in my OpenGL application and I cannot spot the problem.
I have a very basic application, that loads some meshes from 3ds files, builds normals, texture maps and finally display lists. I can move around the scene using mouse and keyboard commands.
I recently added a "LookAt" function, that works pretty much like the gluLookAt function.
Now when I use the new LookAt method something really strange happens. First the camera movement continually gets slower until it completely halted. However, I can stil turn as normal, just cannot move the camera anymore from where it is sitting at this point. The FPS also doesn't change. It still renders each frame as before. Well, and this is also when the scene begins to dissappear. With the eye coords as the center a "black hole" begins to grow, swallowing everything until it fills the entire scene and everything is black. This process only happens when I use the LookAt method. I dont know why it happens or what the actual causes it. I suspect however, that for some reason either my Modelview-Matrix or my Projection-Matrix are "destroyed" or "infected" and this will get worse until said black hole appears and swallows my world :(

I really don't know what happens or why it would happen. It all boils down to the LookAt thing, so I'll give you that code snipept, maybe I'm doing something horrible wrong but just can't figure out what.



void CGLBaseObject::lookAt(const CVector& pos, const CVector &up)
{
CVector f = pos - this->fvPosition;
CVector r = f | up;
CVector u = r | f;

this->m_fmTransform.r = r;
this->m_fmTransform.u = u;
this->m_fmTransform.f = f;

this->m_fmTransform.orthonormalize();
}

m_fmTransform is an CMatrix object containing the modelview matrix which is loaded before the objects display list is rendered - in case of the camera nothing is rendered of course.
CMatrix::orthonormalize() simply normalizes the matrix' position, up and right components.
I believe the CVector class and the CMatrix class work fine, if someone believes the flaw could be located within those I could provide their code aswell.

Has anyone any suggestions what I should look for? Is this maybe even a common problem? Is it possible that this origins from some sort of floating point precision error or is OpenGL trying to tell me "Hey, bitch, use gluLookAt!"?!

Any suggestions, hints or links would be really helpfull.

Greets,
Daniel

trinitrotoluene
11-22-2008, 08:34 PM
These instructions


CVector f = pos - this->fvPosition;
CVector r = f | up;
CVector u = r | f;

are "interesting". First, if the resulting vector f is colinear or near colinear with up, this can bring trouble (zero length vector). Second if pos is near this->fvPosition f can be a zero length vector.



Now when I use the new LookAt method something really strange happens. First the camera movement continually gets slower until it completely halted. However, I can still turn as normal, just cannot move the camera anymore from where it is sitting at this point.

Can you retrieve the coordinate where is the halted position. Then compare it with this->this->fvPosition and verify the value of resulting vectors.

If the position described by this->fvPosition is similar as the center parameter of gluLookAt (http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml), I think that the f vector should be equal to this->fvPosition - pos. And by the way, check to see if you are constructing your matrix in the same way as gluLookAt. Don't forget that if somewhere you use glMultMatrix (http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml) or glLoadMatrix (http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml), OpenGL store it's matrix in column major order.

For the last thing, make sure you call glLoadIdentity() at the beginning of your rendering loop just before setting the LookAt matrix to avoid that your current LookAt matrix will be multiplied with the previous one. In latter case, object appear to drift away. In the end no object will be appearing in the screen because they will be out of clipping plane.

TSorcerer
11-22-2008, 08:48 PM
Ok, I believe I have fixed it.
I was right about that matrix destruction thing. The modelview matrix was scaled smaller with each rendered scene until it finally was all 0. I only have 3 functions that actually manipulate the modelview matrix, that are a translation, a rotation and the LookAt methods. I first looked into the LookAt method, because the bug would appear shortly after I called the LookAt method (through a "key binding").
I found a bug I had in the method. If I used a position vector of another object in for the LookAt function that vector would have taken directly from the objects modelview matrix. It's w-component (the 4th component) would then be 1. This however would have influence on the new base I build in the LookAt method and finally could cause strange behaviour (eg the Vectors magintude would be larger than it is, because of it's w-component not beeing 0 etc).
I fixed that. However, the bug remained.

I then looked into translation method. Nothing spectacular happening there. I only add direction * velocity to the position vector. I figured the method should work.

Finally I looked into my rotation method. For rotating an object I use OpenGL functions. I load the objects modelview matri onto the OpenGL matrix stack, call Rotatef and restore it into the objects local copy with glGetFloatv. When I stepped through this method I recognized that even if I provided the glRotatef function with all zeros as parameters for x,y,z it would actually alter the matrix. It didn't change it drastically, but a few digits behind the decimal point the values would be slightly smaller than before the call. The glRotatef function seemed to shrink my matrix by a small amount each time I called it with all x,y,z zeros.
Because I was calling the rotate method each time before I renedered the scene using mouse deltas (for mouse view) my camera's modelview matrix would slowly be crunshed to death.

I simply added a check if all parameters are set to 0 and then wouldn't call glRotatef. However, I believe this is non-intended behaviour and should be considered a bug in OpenGL - or am I wrong?

PS: I still don't know though why the problem would only occur after I called LookAt. There doesnÄt seem to be any other connection with that method up until now.

trinitrotoluene
11-22-2008, 09:50 PM
The glRotatef function seemed to shrink my matrix by a small amount each time I called it with all x,y,z zeros.
Because I was calling the rotate method each time before I rendered the scene using mouse deltas (for mouse view) my camera's modelview matrix would slowly be crunshed to death.

This behavior is normal. Don't call glRotate multiple time like this: glRotatef(delta,...);. It's better to calculate the final rotation angle of an object like this: object_rotation += delta then call once glRotatef(object_rotation,...). So your matrix will not vanish in time. This is due to floating precision error accumulation.