How do I diagnose jiggling?

Started by scorsh, November 03, 2013, 16:12:42

Previous topic - Next topic

scorsh

Last week, I had zero experience with matrix math, OpenGL, and LWJGL. Using the LWJGL tutorials, some YouTube videos, and reading lots of articles and forum posts over and over and over, I was able to write a silly little program. It displays a grid for X,Y,Z axes and also renders two textured blocks. It uses VBOs and texturing/positioning is done with shaders (i.e., I pass model matrix, view matrix, and projection matrix to fragment shader). When I run the prototype and swivel the camera around, everything looks good and solid.

After I migrated the code into another program, the blocks jiggle as the camera swivels up/down or left/right. It draws a little higher than expected then draws lower again as the camera continues to move.

I've made sure both programs use the same display parameters and there are no differences (AFAICT) in java code or GLSL, but the jiggling still occurs in the one and not the other.

Following is a video that shows what I mean. It's easier to see the jiggling when the video is full screen. Warning: It may hurt your eyes or cause nausea.

How do I diagnose the cause of this problem?

http://www.youtube.com/watch?v=GdArpiLq0RE

Cornix

Without seing any code we will hardly be able to tell you what is going on.
Are the vertices static or do you upload the vertex data continuously? Like some kind of animation maybe?

scorsh

> Without seing any code we will hardly be able to tell you
> what is going on.

I understand. I was unsure of forum etiquette for doing so. There's more code than I'd want to paste into a forum post. So I trimmed it down to as little as possible and attached it to this reply as a zip file. It includes everything needed to run.

The main program is in \src\proto1.game\DefaultGame.java. That's where it sets up the display and starts the game loop.

> Are the vertices static or do you upload the vertex data continuously?
> Like some kind of animation maybe?

At this point it is laughably inefficient.

1. The class proto1.client.states\PlayingState initializes openGL, creates 2 instances of the Block class, renders the grid, and renders the blocks.

2. The Block class is in proto1.world.blocks\Block.java. On every frame, it sets up the vertices, VBOs, etc. and sends them to OpenGL.

I've read about more efficient ways to do this (e.g., set up one mesh with vertices for all block faces to be rendered) but wanted to solve this problem before I took that next step.

*Is it* possible to send the VBOs to OpenGL once and then send again the next time the data changes (e.g., a player removes a block)?


Cornix

Quote from: scorsh on November 03, 2013, 18:17:53On every frame, it sets up the vertices, VBOs, etc. and sends them to OpenGL.
If you send the data everytime, might it be that you cast types somewhere? (from ints to floats)
That would explain the rough movements.

Quote from: scorsh on November 03, 2013, 18:17:53*Is it* possible to send the VBOs to OpenGL once and then send again the next time the data changes (e.g., a player removes a block)?
Of course. Thats what the buffers are good for.
You set them up once and then you keep them for rendering. When something changes you update the contents in the buffers as necessary. There are different ways to do so. You can either call glBufferData to upload the entire buffer everytime something changes. This is good if it doesnt change often but when it changes its a huge change.
Or you can use glBufferSubData which can update only a certain range within the buffer. This is better if there are only small changes every now and then.
There is other methods too, like glMapBuffer. However, I dont quite know how this is implemented in LWJGL as I guess it wouldnt work like in C.

scorsh

Here's what I figured out:

1. In the original prototype, the game loop was calling processInput followed by a call to update (i.e., update block positions based upon input)

2. When I migrated the code, the game loop was calling update followed by processInput. Switching the order resolved the issue.