Camera movement not tied to actual frame rate?!?!?
by Edward Rotberg · in Torque 3D Professional · 03/30/2010 (10:39 am) · 36 replies
We've been noticing an odd stuttering effect in the camera rotation movement (Newtonian movement turned ON). If during this "panning", we pass an area where our scene gets a bit more complex, the motion starts to stutter. So I started examining the code in T3D/camera.cpp. From what I can read there, there is no consideration given to the actual time elapsed during the last frame, rather when time is used at all in the calculations it is "TickSec" which is a constant.
Proper motion should be based upon the actual time elapsed each frame, and I'm surprised that things have looked as good as they do if I am reading this code correctly. Therefor, I think I'm missing something here. Can someone please tell me if I'm reading this code right? If the actual time elapsed in the last frame is used, where is that in the code? What else might be causing this problem?
Thanks in advance for any insight you can offer.
= Ed =
Proper motion should be based upon the actual time elapsed each frame, and I'm surprised that things have looked as good as they do if I am reading this code correctly. Therefor, I think I'm missing something here. Can someone please tell me if I'm reading this code right? If the actual time elapsed in the last frame is used, where is that in the code? What else might be causing this problem?
Thanks in advance for any insight you can offer.
= Ed =
About the author
#2
interpolateTick() is responsible for this interpolation.
Do you have vsync enabled ?
I see some sort of jerky interpolation only working in windowed mode,fullscreen is fine.
03/30/2010 (11:36 am)
Yes,the camera interpolates between the ticks (32 ms).interpolateTick() is responsible for this interpolation.
Do you have vsync enabled ?
I see some sort of jerky interpolation only working in windowed mode,fullscreen is fine.
#3
= Ed =
03/30/2010 (12:07 pm)
I don't see an option for vSync enable/disable. Is this done in the code? As for full screen, I am seeing the opposite of what you are. In full screen, I'm seeing the jerkiness even when the framerate is well above 60 FPS. In windowed mode, there seems to be a threshold where it disappears. Obviously I need to do more testing to quantify this.= Ed =
#4
03/30/2010 (12:12 pm)
I think you can enable/disable vsync with $pref::Video::disableVerticalSync from script.
#5
= Ed =
03/30/2010 (12:56 pm)
Thanks Stefan. Enabling verticalSync (setting disableVirticalSync to 0) did not seem to help the issue at all. I saw no change, and it sort of doesn't make any sense anyhow with an LCD display.= Ed =
#6
03/30/2010 (2:34 pm)
Do you happen to have TimeOfDay running? Try turning it off. I have slight issues with it running with the camera. Not sure if it is just too much refreshing going on with the shadows, but it does cause a bit of a noticeable stutter with the camera for me when rotating.
#7
Thanks
= Ed =
EDIT: I verified this by putting a breakpoint on the constructor for the TimeOfDay class and it was never reached.
03/30/2010 (2:44 pm)
I believe that TimeOFDay is only associated with a ScatterSky, which I don't believe that we have in the level in question. Good thought though. If there is another way to enable TimeOfDay than via a scatter sky, please let me know how to find it.Thanks
= Ed =
EDIT: I verified this by putting a breakpoint on the constructor for the TimeOfDay class and it was never reached.
#8
If you disable newtonian movement does it go away?
03/30/2010 (6:25 pm)
This sounds like a bug in the Camera objects networking (single player Torque still does short-circut networking) or the interpolation code.If you disable newtonian movement does it go away?
#9
I've noticed this too. it seems to go away when I switch to full-screen. unfortunately, since the editor has to be run in windowed mode, I see it very often.
I believe this is always happening, but its less noticeable when the camera's moving forward or backward and when the framerate is very high. I think that's what makes it deceiving. you may think that removing some particular object makes the problem go away, but I dont think its tied to any particular object so much as its just dependent on framerate.
normally, a low framerate will result in choppiness of the scene rendering. but this isn't choppiness, its a stuttering as if the camera or object transform is slightly off every second or third frame. at least thats what i looks like to me.
when I look closely at objects while moving the camera around, I will periodically notice it actually moving smoothly for a split second, then it goes back to stuttering.
I think this is a bug.
03/30/2010 (9:09 pm)
I think Ive seen this stuttering mentioned before.I've noticed this too. it seems to go away when I switch to full-screen. unfortunately, since the editor has to be run in windowed mode, I see it very often.
I believe this is always happening, but its less noticeable when the camera's moving forward or backward and when the framerate is very high. I think that's what makes it deceiving. you may think that removing some particular object makes the problem go away, but I dont think its tied to any particular object so much as its just dependent on framerate.
normally, a low framerate will result in choppiness of the scene rendering. but this isn't choppiness, its a stuttering as if the camera or object transform is slightly off every second or third frame. at least thats what i looks like to me.
when I look closely at objects while moving the camera around, I will periodically notice it actually moving smoothly for a split second, then it goes back to stuttering.
I think this is a bug.
#10
03/30/2010 (9:43 pm)
I read somewhere that the speed in the datablock and camera class should be equal or there is jittering. I believe it was 40 by default.
#11
@Adam: I'll look into this as well, though this would point to a deeper problem as the camera speed should be totally overridable dynamically.
= Ed =
EDIT: I slowed down the max rotation speed and it still appears to be stuttering. Still hacking away at this.
03/31/2010 (9:21 am)
@Tom: I disabled newtownion rotation (that's where I'm seeing this), and since the motion seems significantly faster that with newtownian, it's not a completely direct comparison. However, as best I can tell, it still seems jerky. It's hard to be sure though. I'll try to change the max rotation rate to make them more comparable and re-edit this response.@Adam: I'll look into this as well, though this would point to a deeper problem as the camera speed should be totally overridable dynamically.
= Ed =
EDIT: I slowed down the max rotation speed and it still appears to be stuttering. Still hacking away at this.
#12
I'm afraid of this has nothing to do with the camera interpolation.
I'm using my own camera system and still see this.
I did a few testing:
Ati x1950 xtx
800 X 600 , vsync on, stuttering
1024 X 768 , vsync on, stuttering
1280 X 1024 , vsync on, no stuttering
Ati 3870
800 X 600 , vsync on, stuttering
1024 X 768 , vsync on, stuttering
1280 X 1024 , vsync on, no stuttering
windowed = stuttering
fullscreen at high resolutions = no stuttering
All this appears to be a driver issue.
04/02/2010 (2:36 am)
Edward,I'm afraid of this has nothing to do with the camera interpolation.
I'm using my own camera system and still see this.
I did a few testing:
Ati x1950 xtx
800 X 600 , vsync on, stuttering
1024 X 768 , vsync on, stuttering
1280 X 1024 , vsync on, no stuttering
Ati 3870
800 X 600 , vsync on, stuttering
1024 X 768 , vsync on, stuttering
1280 X 1024 , vsync on, no stuttering
windowed = stuttering
fullscreen at high resolutions = no stuttering
All this appears to be a driver issue.
#13
At 30 fps the render becomes jerky, which is unusual.
Definitely not a driver issue!
I tried different values of timeManagerProcessInterval,the render is even worse.
When I delete the water and the framerate goes up,the camera remains jerky.
I tried a different way to load the scene - I used hundreds of debrises. The fps goes down to 11 and the camera goes a bit jerky (it is normal). When the debrises are gone and the framerate recovers - the camera becomes good again. (This is a correct behaviour)
That proves the framerate isn't the reason for the camera's jerky behaviour.
04/02/2010 (8:05 am)
OK,when I add a water block, I see the stuttering all the time.At 30 fps the render becomes jerky, which is unusual.
Definitely not a driver issue!
I tried different values of timeManagerProcessInterval,the render is even worse.
When I delete the water and the framerate goes up,the camera remains jerky.
I tried a different way to load the scene - I used hundreds of debrises. The fps goes down to 11 and the camera goes a bit jerky (it is normal). When the debrises are gone and the framerate recovers - the camera becomes good again. (This is a correct behaviour)
That proves the framerate isn't the reason for the camera's jerky behaviour.
#14
A possibility: it may not be using the correct transform for the player position...maybe should use rendertransform instead. This can look like it's affected by framerate (which it is i suppose) as I've run into this before. Is the jerkiness affected by the world position/rotation of the camera?
Another thought I had: possibly a precision issue for the camera transform... client vs server. Does the symptom increase with distance to the world center (if using a compressed point in the update, this may not matter much)? I've noticed this jitter of the player to correspond with the water block z-fighting with the terrain at times too.
04/02/2010 (8:23 am)
Ive noticed this for a while... havent had time to dig into it myself but I've had a couple of thoughts on it and thought I'd chime in.A possibility: it may not be using the correct transform for the player position...maybe should use rendertransform instead. This can look like it's affected by framerate (which it is i suppose) as I've run into this before. Is the jerkiness affected by the world position/rotation of the camera?
Another thought I had: possibly a precision issue for the camera transform... client vs server. Does the symptom increase with distance to the world center (if using a compressed point in the update, this may not matter much)? I've noticed this jitter of the player to correspond with the water block z-fighting with the terrain at times too.
#15
When I delete the water block,I get over 200 fps and the camera is still jerky.
If water is not used at all - everything is fine.
04/02/2010 (9:06 am)
It is not related to the framerate, it is the water block.When I delete the water block,I get over 200 fps and the camera is still jerky.
If water is not used at all - everything is fine.
#16
= Ed =
04/02/2010 (9:16 am)
We don't even use a water block, and we are still seeing this. Has anyone tried this on a separated client from the server? I plan to do this when I next get a chance to look into this further.= Ed =
#17
Let's assume that we have 60+ framerate, when we have vsync on,it means that each frame happens at 16,67 ms , processTick happens each 32 ms
I put several console prinfs in interpolatetick() and processTick() and what I see is this:
interpolateTick
interpolateTick
processTick
This happens 8 times,on the 9th time I have a single interpolateTick - this is normal ,because we have 0,67 ms time difference.
OK,so far all is well.
Let's load the scene a lot - I create many items,debrises,explosions - all is fine again.
OK,now let's load the scene with a terrain,water....
I still have 60 fps,but in console:
interpolateTick
processTick
interpolateTick
processTick
...
And here is the problem - interpolateTick is called per 32ms - this is incorrect and it happens not only to the camera,but to all objects in the scene. For example the player can not pick an item due to an incorrect position,caused by a lack in the interpolation.
I found that when I put a water object,the whole synchronization and interpolation goes mad.
This should be submitted as a bug.
04/06/2010 (1:34 am)
I found what is wrong.Let's assume that we have 60+ framerate, when we have vsync on,it means that each frame happens at 16,67 ms , processTick happens each 32 ms
I put several console prinfs in interpolatetick() and processTick() and what I see is this:
interpolateTick
interpolateTick
processTick
This happens 8 times,on the 9th time I have a single interpolateTick - this is normal ,because we have 0,67 ms time difference.
OK,so far all is well.
Let's load the scene a lot - I create many items,debrises,explosions - all is fine again.
OK,now let's load the scene with a terrain,water....
I still have 60 fps,but in console:
interpolateTick
processTick
interpolateTick
processTick
...
And here is the problem - interpolateTick is called per 32ms - this is incorrect and it happens not only to the camera,but to all objects in the scene. For example the player can not pick an item due to an incorrect position,caused by a lack in the interpolation.
I found that when I put a water object,the whole synchronization and interpolation goes mad.
This should be submitted as a bug.
#18
EDIT: My Aplogies!! I just noticed that you were referring to processTick() being called every 32ms, not interpolateTick(). I really should look into the method of how and when that is called before I comment further. = Ed =
Below is an excerpt from the output. Clearly interpolateTick() is not being called at 32ms intervals.
04/06/2010 (9:22 am)
Hmmmm, I don't think that inerpolateTick() is called on 32ms intervals, after all, it can accept any dt value. So in order to determine if this was true, I just put a Con::printf() call at the first line of Camera::interpolateTick(). Granted, this is a clear case of the Heisenberg Principle in operation, as performing the printf at every interpolateTick() will definitely affect performance, but I figured there was something to be learned.EDIT: My Aplogies!! I just noticed that you were referring to processTick() being called every 32ms, not interpolateTick(). I really should look into the method of how and when that is called before I comment further. = Ed =
Below is an excerpt from the output. Clearly interpolateTick() is not being called at 32ms intervals.
0.72 ms 0.47 ms 0.25 ms 0.03 ms 0.81 ms 0.56 ms 0.31 ms 0.06 ms 0.84 ms 0.59 ms 0.38 ms 0.13 ms 0.94 ms 0.69 ms 0.44 ms 0.22 ms 0.00 ms 0.78 ms 0.56 ms 0.34 ms 0.09 ms 0.88 ms 0.63 ms 0.41 ms 0.19 ms 0.94 ms 0.69 ms 0.47 ms 0.25 ms 0.03 ms 0.78 ms 0.59 ms 0.38 ms 0.19 ms 0.03 ms 0.84 ms 0.63 ms 0.44 ms 0.22 ms 0.00 ms 0.75 ms 0.53 ms 0.28 ms 0.06 ms 0.81 ms
#19
The network guard is ok - no problems,but I see bad things on my screen.
I found something interesting.I'm using these prefs:
$pref::Net::PacketRateToClient = "32";
$pref::Net::PacketRateToServer = "32";
$pref::Net::PacketSize = "450";
When I switch to:
$pref::Net::PacketRateToClient = "30";
$pref::Net::PacketRateToServer = "30";
$pref::Net::PacketSize = "450";
Now I see the jittering all the time.
interpolateTick() does not work correctly,it is called per 32ms at 60 fps - this is bad. This happens sometimes on a loaded scene.
I have no solution so far.
04/06/2010 (9:28 am)
Something different happens on my PC - may be a network issue..?!?The network guard is ok - no problems,but I see bad things on my screen.
I found something interesting.I'm using these prefs:
$pref::Net::PacketRateToClient = "32";
$pref::Net::PacketRateToServer = "32";
$pref::Net::PacketSize = "450";
When I switch to:
$pref::Net::PacketRateToClient = "30";
$pref::Net::PacketRateToServer = "30";
$pref::Net::PacketSize = "450";
Now I see the jittering all the time.
interpolateTick() does not work correctly,it is called per 32ms at 60 fps - this is bad. This happens sometimes on a loaded scene.
I have no solution so far.
#20
processTick() is designed to work in conjunction with interpolateTick() which does indeed handle interpolating smoothly over arbitrary delta times. ITickable's advanceTime() is called with variable dt. I assume that it is called once per logical frame. However, I just don't see the point of making cameras run as ITickable Objects. Why not just update the camera one each frame just before the frame is rendered. Let it do any motion calculations that it has to based upon the actual dt instead of breaking it into 32 ms chunks.
I'm sure it's my lack of understanding of how and why the ITickable objects are intended to be used. It seems to me that they perform a useful function only if the frame rate gets very slow. For faster frame rates, especially those shorter than 32ms, it seems that the current ITickable process causes unnecessary motion artifacts, that could be avoidable by using a brain-dead approach of just doing the interplateTick/processTick work at the current delta time rather than accumulating deltas into 32ms chunks and making multiple processTick() during some frames. This technique appears to inherently be capable of creating the stuttering as the actual camera matrices are only ever updated at 32ms intervals, [i]with truncation used for fractional intervals[i].
It is tempting to rewrite advanceTime to just call interpolateTick and processTick in that order once for each ITickable object, thus letting the camera and other objects "free run". However, not being completely familiar with the entire inner workings of T3D, I could also imagine that this is a very silly idea.
So basically, I'd like to hear from someone who has the necessary gestalt understanding of T3D to explain the rationale behind the ITickable concept. It would probably greatly advance my understanding of T3d in general.
= Ed =
04/06/2010 (10:02 am)
Ok, I've just gone through ITickable to see how this is all being handled, and honestly, this looks like archaic code that is indeed in need of an overhaul. The premise here is that objects that inherit fro ITickable require a processTick() call for every 32 ms that pass. This makes perfect sense for cameras if you are using a system that can only update the display every 32 ms. For LCD displays, not so much. For CRT displays it makes sense only to the extent that you don't want to be calling these processTick() functions too often. Otherwise, why not 16ms?processTick() is designed to work in conjunction with interpolateTick() which does indeed handle interpolating smoothly over arbitrary delta times. ITickable's advanceTime() is called with variable dt. I assume that it is called once per logical frame. However, I just don't see the point of making cameras run as ITickable Objects. Why not just update the camera one each frame just before the frame is rendered. Let it do any motion calculations that it has to based upon the actual dt instead of breaking it into 32 ms chunks.
I'm sure it's my lack of understanding of how and why the ITickable objects are intended to be used. It seems to me that they perform a useful function only if the frame rate gets very slow. For faster frame rates, especially those shorter than 32ms, it seems that the current ITickable process causes unnecessary motion artifacts, that could be avoidable by using a brain-dead approach of just doing the interplateTick/processTick work at the current delta time rather than accumulating deltas into 32ms chunks and making multiple processTick() during some frames. This technique appears to inherently be capable of creating the stuttering as the actual camera matrices are only ever updated at 32ms intervals, [i]with truncation used for fractional intervals[i].
It is tempting to rewrite advanceTime to just call interpolateTick and processTick in that order once for each ITickable object, thus letting the camera and other objects "free run". However, not being completely familiar with the entire inner workings of T3D, I could also imagine that this is a very silly idea.
So basically, I'd like to hear from someone who has the necessary gestalt understanding of T3D to explain the rationale behind the ITickable concept. It would probably greatly advance my understanding of T3d in general.
= Ed =
Torque 3D Owner Edward Rotberg
However it still doesn't answer why I am seeing this stuttering when I am just rotating the camera. Some more data points on the stuttering are probably in order:
1) The stuttering is most noticeable (obviously) when the FOV is pretty narrow.
2) The stuttering becomes noticeable when the framerate drops below about 60 FPS. It's pretty smooth above that.
That's about all I can think of for now.
= Ed =