PDA

View Full Version : Got my maths wrong somewhere



Stuart McDonald
10-12-2010, 01:40 PM
Hopefully someone can point in the right direction to track down this problem. Everything in my code works fine except for one thing, I have to rotate my models 180 degrees about the Y-axis from what I expect. E.g.

If I create a single triangle, CCW winding, place it at 0,0,0 and my camera at 0,0,-100 looking towards it I don't see it. If I rotate it 180 about the Y I do see it. Similarly if I move the camera to 0,0,100 looking at 0,0,0 then I see it.

[EDIT: Whoops the 100/-100 are the wrong way around. I want to have -ve Z going into the screen, +ve Y up amd +ve X right. When I use the camera at -100 +ve X it left i.e. if I increase the objects X it moves left]

I've got glFrontFace(GL_CCW) and glCullFace(GL_BACK) so I guess the problem is in a matrix somewhere. Trouble is, my maths is weak and I actually wrote all this years ago.

Can anyone at least point me at areas to look at? (or not to look at)

Cheers,

Stuart.

david_f_knight
10-12-2010, 02:24 PM
Did you try calling glDisable (GL_CULL_FACE) for grins? Just to absolutely rule out the possibility that it has something to do with that?

You know, OpenGL does not impose any particular coordinate system (i.e., left-handed or right-handed), though by default it is left-handed. If you changed the handedness of your coordinate system, then a polygon that was defined CCW instantly has a CW definition and vice versa.

If calling glDisable (GL_CULL_FACE) results in your triangle becoming visible, then my suggestion is to look where you changed your coordinate system's handedness (and to double-check that everything you think is true about each of your matrices and triangles and OpenGL states is really so).

All it takes to change the handedness of your coordinate system is just a single multiplication by -1 in the right (or wrong) place. For example, negating one coordinate in all the vertices of your geometry will change the handedness of your data's coordinate system. You can negate a coordinate of your vertices in any matrix you multiply by your vertices just by having a minus sign you don't want, or a plus sign you don't want, in the wrong place.

Stuart McDonald
10-12-2010, 02:33 PM
Yes, disabling GL_CULL_FACE shows my polygon. I figured it's something to do with left/right handed, but I don't know which I'm using. I read the wiki and I'm non the wiser :)

I've edited the first post because I got stuff the wrong way around. Which handedness does that describe? And where can I find what the matrix values should be for which system? As I said I wrote all this years ago and I didn't actually pick left or right handed. Just got stuff to appear :)

Thanks,

Stuart.

david_f_knight
10-12-2010, 02:52 PM
You described a right-handed coordinate system in your first post (after editing it, that is). As I wrote before, all the default values for matrices and so on in OpenGL assume a left-handed coordinate system.

Depending on what you're doing, you might just be able to leave back face culling disabled. Typically, it is enabled just for performance improvements, but if you are not experiencing performance problems with your program, then the easiest answer of all is to just disable back face culling. (That can impact your lighting calculations later on, though, because your surface normals will all be pointing the opposite direction from what they should be if they were calculated assuming the other handed coordinate system.)

Another really easy answer is to just call glFrontFace(GL_CW) or glCullFace(GL_FRONT) (but NOT both!).

Another easy fix is to just negate the Z-coordinate of all your geometric model's vertices.

As far as your matrix values go, if you negate the sign of any odd number of values along the diagonal of any matrix, then you change the handedness of your coordinate system.

Whatever you do, do an odd number of them. If you do an even number of them then you end up back where you started (but possibly with unintended side-effects).

Alfonse Reinheart
10-12-2010, 03:44 PM
As I wrote before, all the default values for matrices and so on in OpenGL assume a left-handed coordinate system.

No they do not. OpenGL has always used a right-handed coordinate system for matrices. Camera (eye) space has +X to the right, +Y up, and +Z forward (towards the camera), which is right-handed. Clip-space has +X to the right, +Y up, and +Z forward again, which is right-handed. Same goes for normalized device coordinate space.

Stuart McDonald
10-13-2010, 06:21 AM
Found it. I had a -1 instead of +1 when calculating the facing vector. Thanks for the help.

david_f_knight
10-13-2010, 03:51 PM
No they do not. OpenGL has always used a right-handed coordinate system for matrices.Alphonse, matrices don't have or use any coordinate system. Matrices can transform data from one coordinate system to another. It is data that is characterized by its coordinate system.

For example, if you start with data in a left-handed coordinate system, and multiply it by the identity matrix, the data will come out the other end still in a left-handed coordinate system. If your data was in a right-handed coordinate system, and multiplied by that same identity matrix, the data that comes out the other end will still be in its right-handed coordinate system. The same principle holds for any matrix. It either always transforms or never transforms the coordinate system of the data it is multiplied with, but the matrix itself "has" no coordinate system.

What I wrote previously was correct in the context of the original question, but I could have better qualified what I wrote. OpenGL's default states and matrices assume incoming geometric data is defined in a left-handed coordinate system. That implies nothing about what transformations and coordinate systems may be used downstream within the OpenGL pipeline.

Alfonse Reinheart
10-13-2010, 04:38 PM
It either always transforms or never transforms the coordinate system of the data it is multiplied with, but the matrix itself "has" no coordinate system.

A matrix defines a transformation from one coordinate system to another. If the data being transformed is not actually in the initial coordinate system, then the output data will not be in the expected final coordinate system either.


OpenGL's default states and matrices assume incoming geometric data is defined in a left-handed coordinate system.

No, it does not. The matrices OpenGL generates do not work on left-handed coordinate data. Camera-space, which is defined by the projection matrix (glFrustum and gluPerspective), is a right-handed space. And there is nothing in the modelview matrices that will innately convert left-handed coordinates into right-handed camera-space.

If a sequence of transformations ends in a right-handed coordinate system (for example, clip-space), and none of the transformations cause a change in handedness (no matrix generated by OpenGL will do this), then the initial coordinate system of any incoming vertices is expected to be in a right-handed space.

If you are correct, and the expected coordinate system for vertices in default OpenGL is left-handed, then you should be able to show me what particular default state applies a handedness change to vertex data. Clip-space is right handed, so there must be a handedness transformation in the default state. Where is it? GL_PROJECTION and GL_MODELVIEW start off initially as identity.

david_f_knight
10-14-2010, 02:34 PM
Here is why I claim OpenGL assumes a left-handed coordinate system for data by default:

The default value for glDepthFunc() is GL_LESS.

That means, given that positive X points to the right, and positive Y points up, smaller (eg., negative) Z values are nearer or in front of larger (eg., positive) Z values. That is, negative Z comes out of the screen towards the viewer, and positive Z points into the screen away from the viewer. That defines a left-handed coordinate system.

I use OpenGL 4.0 core profile exclusively, so that is the perspective I am coming from. OpenGL 4.0 core profile has no default matrices, nor any glFrustum() or gluPerspective() functions. It is left to each programmer to decide on whatever convention he desires, and to implement it himself. That's why I use glDepthFunc() as the arbiter of which coordinate system (left- or right-handed) is in use. glDepthFunc() is where the rubber meets the road, and it's easy to understand.


Clip-space is right handed, so there must be a handedness transformation in the default state. Where is it?I don't think Clip Space has any inherent "handedness." Clip Space is a cube defined from -W to +W in all three dimensions. Any coordinate outside that cube, i.e., |X| > W, or |Y| > W, or |Z| > W, will be clipped. There is no inherent front or back in Clip Space, so Clip Space has no inherent "handedness."

P.S. I previously discussed one way of changing the "handedness" of coordinate systems, i.e., by negating all the values of one of the coordinates of all the data's points. There is also another way of changing the "handedness" of coordinate systems: interchange the coordinates of any two dimensions of all the data's points (eg., swap all the Y coordinates for the Z coordinates).

Alfonse Reinheart
10-14-2010, 05:45 PM
I don't think Clip Space has any inherent "handedness."

Actually clip space does have a handedness. The actual value of W cannot change the handedness of clip space. If W is negative, this flips the meaning of each axis, but flipping all of the axes doesn't change handedness.

That being said, clip space, normalized device coordinate space, and window space are all left-handed.

I have no idea how I got that mixed up. I even drew an image (http://www.arcsynthesis.org/gltut/Basics/Introduction.html#d0e382) of it, and the text under it confirms that it's left-handed.

And since the transform from NDC space to clip space can't change the handedness of the space, clip space is left-handed as well.