Same matrix transform code doesn't work in C++

Well, this is more of a question relating to C++ than to java, however it has to do with java and JOGL and I could think of no other place to post it, so I will post it here.

I have spent quite a long time trying to figure out why this strange behavior is exhibited, however I have not been able to come up with an answer, and perhaps the people here much more experienced with JOGL may be able to provide an explanation.

So basically, I created this small function that allows my app to easily switch to rendering between 2d and 3d objects by changing some values of the matrix stacks, namely in GL_PROJECTION and GL_MODELVIEW. I ported this code exactly as is, as well as my initialization code for opengl to C++ (of which I have more experience in than java), however in C++, this code does not produce the same effect as it’s exact counterpart in java does.

Anyways, enough talking, here’s the code.

	public static void setDrawMode(int DrawMode)
	{
		if (CurrentDrawMode != DrawMode)
		{
			switch (DrawMode)
			{
				case DRAWMODE_2D:
				{
					//glDisable(GL.GL_LIGHTING);
					gl.glMatrixMode(GL.GL_PROJECTION);
					gl.glLoadIdentity();
					gl.glOrtho(0, WindowWidth, WindowHeight, 0, 0, 1);
					gl.glDisable(GL.GL_DEPTH_TEST);
					gl.glMatrixMode(GL.GL_MODELVIEW);
					gl.glLoadIdentity();
					// Displacement trick for exact pixelization
					gl.glTranslatef(0.375f, 0.375f, 0f);
					break;
				}
				case DRAWMODE_3D:
				{
					gl.glEnable(GL.GL_DEPTH_TEST);
					gl.glViewport(0, 0, WindowWidth, WindowHeight);
					gl.glMatrixMode( GL.GL_PROJECTION );
					gl.glLoadIdentity();
					gluPerspective( 45.0f, (float)WindowWidth / (float)WindowHeight, 0.1f, 1000.0f);
					gl.glMatrixMode( GL.GL_MODELVIEW );
					gl.glLoadIdentity();
					break;
				}
				default:
				{
					break;
				}
			}
			CurrentDrawMode = DrawMode;
		}
	}

And here’s the version I ported to C++: (uses constants for window sizing for simplicity in tests)

void setDrawMode(int DrawMode)
{
		if (CurrentDrawMode != DrawMode)
		{
			switch (DrawMode)
			{
				case DRAWMODE_2D:
				{
					glMatrixMode(GL_PROJECTION);
					glLoadIdentity();
					glOrtho(0, 800, 600, 0, 0, 1);
					glDisable(GL_DEPTH_TEST);
					glMatrixMode(GL_MODELVIEW);
					glLoadIdentity();
					// Displacement trick for exact pixelization
					glTranslatef(0.375f, 0.375f, 0.0f);
					break;
				}
				case DRAWMODE_3D:
				{
					glEnable(GL_DEPTH_TEST);
					glViewport(0, 0, 800, 600);
					glMatrixMode( GL_PROJECTION );
					glLoadIdentity();
					gluPerspective( 45.0f, (float)800 / (float)600, 0.1f, 1000.0f);
					glMatrixMode( GL_MODELVIEW );
					glLoadIdentity();
					break;
				}
				default:
				{
					break;
				}
			}
			CurrentDrawMode = DrawMode;
		}
}

In the interest of saving people reading, I included only the function to show basically what I’m doing, however if anyone wants the full cpde or whatever, it’s not too long and doesn’t do much so I’d be willing to share it.

So basically, what I’m trying to ask is: why does this code function as expected in java but not in C++. I examined further strange behavior upon trying to do the same matrix transforms… when i tried to just push/pop matrixes from the matrix stack (in C++) instead of loading identities over and over (like the java code does), it works… this is driving me crazy as to my knowledge, this should result in exactly the same matrixes being formed, but it seems it doesn’t function as expected? I’m not sure anymore…

I now resorted to using the push/pop-ing of matrixes in C++ as a solution to achieve the effect I want (seeing is it’s probably faster as well), however just for my own knowledge I would really like to know why this doesn’t work although it (theoretically?) should… maybe JOGL does something strange here?

Actually it should not be any different. Look for other bugs and typos like missing breaks, other stuff modifying the matrices etc. I assume you are completely single threaded!?

Yes, both the java app as well as the c++ app in question are single threaded. I also know I’m not missing breaks or any other syntax-related differences because I literally copy-pasted this function into the C++ app and just removed the gl. before the API calls to essentially port it over. I also know I’m not modifying the matrices any other way because I tested it in a C++ app that was as small as possible, with just opengl init and this code and drawing a couple quads, still did not match the behavior in java…

I mean, my only guess at this point is that JOGL doesn’t directly wrap all these API’s and does some additional stuff underneath which causes this discrepancy in behavior when I try to directly port the code…

Can you try reading the modelview and projection matrices back from OpenGL in both the JOGL and C++ versions to see if their 4x4 matrices are different?

You can use glGetFloatfv() for that.

I made a function to read the matrices in both JOGL and C++ and printed the results out at different states in both JOGL and C++ scenarios. I noticed no differences except for some negative 0 values in the modelview matrix after both a 3d draw mode set and an update camera call (the last result in both sets). UpdateCamera() is just a separate function that I haven’t posted, which serves to modify the view in a manner that reflects a set of camera variables like rotation and position. Do these negative 0s affect anything? I’m not really sure, as 0 can’t really be negative as far as I know…

Full results in both JOGL and C++ with the camera being in exactly the same position are below.

Java:

Initial state:
GL_PROJECTION
1.000000 0.000000 0.000000 0.000000 
0.000000 1.000000 0.000000 0.000000 
0.000000 0.000000 1.000000 0.000000 
0.000000 0.000000 0.000000 1.000000 
GL_MODELVIEW
1.000000 0.000000 0.000000 0.000000 
0.000000 1.000000 0.000000 0.000000 
0.000000 0.000000 1.000000 0.000000 
0.000000 0.000000 0.000000 1.000000 


After setDrawMode(DRAWMODE_3D);
GL_PROJECTION
1.810661 0.000000 0.000000 0.000000 
0.000000 2.414214 0.000000 0.000000 
0.000000 0.000000 -1.000200 -1.000000 
0.000000 0.000000 -0.200020 0.000000 
GL_MODELVIEW
1.000000 0.000000 0.000000 0.000000 
0.000000 1.000000 0.000000 0.000000 
0.000000 0.000000 1.000000 0.000000 
0.000000 0.000000 0.000000 1.000000 


After setDrawMode(DRAWMODE_2D);
GL_PROJECTION
0.002500 0.000000 0.000000 0.000000 
-0.000000 -0.003333 -0.000000 -0.000000 
-0.000000 -0.000000 -2.000000 -0.000000 
-1.000000 1.000000 -1.000000 1.000000 
GL_MODELVIEW
1.000000 0.000000 0.000000 0.000000 
0.000000 1.000000 0.000000 0.000000 
0.000000 0.000000 1.000000 0.000000 
0.375000 0.375000 0.000000 1.000000 


After setDrawMode(DRAWMODE_3D); and UpdateCamera();
GL_PROJECTION
1.810661 0.000000 0.000000 0.000000 
0.000000 2.414214 0.000000 0.000000 
0.000000 0.000000 -1.000200 -1.000000 
0.000000 0.000000 -0.200020 0.000000 
GL_MODELVIEW
1.000000 -0.000000 -0.000000 0.000000 
0.000000 1.000000 -0.000000 0.000000 
0.000000 0.000000 1.000000 0.000000 
0.000000 0.000000 0.000000 1.000000 

C++:

Initial state:
GL_PROJECTION
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000
GL_MODELVIEW
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000


After setDrawMode(DRAWMODE_3D);
GL_PROJECTION
1.810661 0.000000 0.000000 0.000000
0.000000 2.414214 0.000000 0.000000
0.000000 0.000000 -1.000200 -1.000000
0.000000 0.000000 -0.200020 0.000000
GL_MODELVIEW
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000


After setDrawMode(DRAWMODE_2D);
GL_PROJECTION
0.002500 0.000000 0.000000 0.000000
-0.000000 -0.003333 -0.000000 -0.000000
-0.000000 -0.000000 -2.000000 -0.000000
-1.000000 1.000000 -1.000000 1.000000
GL_MODELVIEW
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.375000 0.375000 0.000000 1.000000


After setDrawMode(DRAWMODE_3D); and UpdateCamera();
GL_PROJECTION
1.810661 0.000000 0.000000 0.000000
0.000000 2.414214 0.000000 0.000000
0.000000 0.000000 -1.000200 -1.000000
0.000000 0.000000 -0.200020 0.000000
GL_MODELVIEW
1.000000 -0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
-0.000000 -0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000

Any ideas?

The -0’s shouldn’t affect anything. I know you said the setDrawMode() was copied from Java to C++, but are the rest of the app’s identical too? Maybe there’s a weird bug somewhere else that is screwing up.

Also, how exactly is the C++ version failing? Does nothing show up, or does it show up incorrectly?

As far as I know, JOGL does not do anything fancy when it wraps OpenGL, it just does data transmission.

What version of OpenGL are you running? Could it be possible that C++ is selecting a different version or profile?

I’ve checked it over and my initialization code is exactly the same in terms of opengl calls made in both test code pieces. In terms of how the C++ version fails, geometry is displayed however everything basically takes on a 2d mode and there doesn’t seem to be any 3d depth or other transformations going on, everything drawn is 2d (changing the camera’s position on the z axis, for example, does not make the geometry change displayed size in C++ like it does in java…). As far as opengl version, as far as I know they should both be using the same version as I have not messed with my opengl to add different versions or anything like that.

Since the code produces identical matrices, you have another bug in your c++ code. Add some messages at the beginning of setdrawmode - I bet it is unintentionally called from somewhere with 2D mode…

Oh, what you said reminds me of another thing I tried. I tried calling only setDrawMode with only DRAWMODE_3D every frame, and depth and all that worked fine. It’s only as soon as I added a single call to it with DRAWMODE_2D afterwards to draw some 2d stuff that everything started to only draw in 2d (even the parts before the draw mode should be set to it). In my tests, I only call the function twice per frame, once for 3d at the beginning, draw a quad, then again for 2d and draw another quad, so I know that it’s not being called to set 2d somewhere randomly by accident when the drawmode should be 3d. Since the draw mode is being set back to 3d at the beginning of every frame for the geometry that should be drawn in 3d, setting it to 2d later in a frame should still allow the geometry drawn beforehand to be in 3d, but it still appears to be drawn in 2d. Any other ideas?

But in Java, you can run DRAWMODE_3D and then DRAWMODE_2D every frame correctly?

Also, just so we can rule out the possibility of human error, can you post your C++ version of the function, even if you think it looks the same?

Yes, in Java with JOGL, I can change the draw mode exactly the same way per frame, and upon drawing the same geometry, what should be 3d is 3d and what should be 2d is 2d.

I have also updated my original post with the C++ port as you requested, as you can see it’s very similar and it was really a matter of copy + paste and some minor changes.

You resist the road to salvation :wink:

Your posted code produces the same matrices in Java or C++, so why should there be an error in there? Also JOGL does absolutely nothing else than calling the OpenGL functions. The error clearly is elsewhere, so you have to verify the control flow of your application. If you say, you know, that setDrawMode(2D) is not called but don’t prove it, you know nothing.

Take it with the Sherlock Holmes quote: “When you have eliminated the impossible, whatever remains, however improbable, must be the truth”

There must either be an extra callback in the C++ code (what are you using to set up a window? SDL?), that resets the draw mode or you set CurrentDrawMode = DrawMode somewhere else, so that the if (CurrentDrawMode != DrawMode) is always false. Try to verify the former by adding debug messages and verify the latter, by removing the drawmode check.

I did try logging calls to the setDrawMode function and the mode being set, and as the log proved, every frame setting draw mode to 3d first was called once, then setting draw mode to 2d was called once after. No unexpected behavior there. I am also sure that the current draw mode is not set anywhere else, and I did also try removing that check entirely as well. All of this made no difference on the issue at hand. Maybe I should just post the full code I’m using to test?

Oh wow, I finally managed to solve this…

Turns out that it wasn’t even this function that was causing the problem… My UpdateCamera function was based on the matrix transforms that D3DXMatrixLookAtLH does, and it turns out that while for some reason JOGL allows the camera to work fine with these matrix transforms, in C++ this resulted in the geometry being culled out or something about that effect as soon as the CamLocZ variable hit -1.0. I changed up the matrix transforms that UpdateCamera does, and now I have the perfect coordinate system I wanted and it works just great in C++. I applied the same changes to the JOGL version and the camera worked great in there too. I don’t know why, but after days of fiddling with this, I just decided to screw around with the UpdateCamera function, and it almost magically just worked afterwards.

As of now, this problem is resolved. In the end, it was my fault for identifying the actual problem incorrectly. I suppose the reason this doesn’t occur in java is because all types are 64-bit sized by default so there was higher precision maintained in the matrix values while since the C++ app is a native 32-bit app, that precision was lost and it resulted in premature culling or some other problem to occur which resulted in the geometry disappearing. I might not be 100% correct about that, but what I do know is changing a couple negatives in the UpdateCamera function’s matrix generation into positives was essentially what solved this problem.

It turns out the reason I thought it just wasn’t working at all was because of the size of the geometry that I was testing with, it was quite large and as the cut-off distance of the camera was a tiny -1.0, I couldn’t even notice that the object was actually appearing smaller. That was part of the reason that led to this misconception. As I was approaching this solution, to test my theory, I tried testing with a much smaller piece of geometry and I did indeed notice it appearing smaller, which eventually led me to the final solution.

I appreciate the help of everyone who contributed to this thread, thanks guys.