Juddering Camera
by Ian Omroth Hardingham · in Torque Game Engine · 03/10/2004 (5:05 am) · 12 replies
Hey everyone,
I'm writing a new camera class which needs to track two players fighting. My camera class extends Camera and I've written the following processTick method:
However, the camera judders horribly. I've checked all the obvious things: focusPoint is the same on client and server, tried just simply moving the camera a constant distance each tick, and the juddering reamins.
So I'm guessing this has something to do with the camera only being moved every tick rather than every frame on the client. Am I heading in the right direction? How can I call a function every frame on the client? Or is the juddering something else entirely?
Any help much appreciated,
Ian
I'm writing a new camera class which needs to track two players fighting. My camera class extends Camera and I've written the following processTick method:
void WapCam::processTick(const Move* move)
{
if (mPlayer && mOpponent)
{
Point3F playerPos = mPlayer->getRenderTransform().getPosition();
Point3F opponentPos = mOpponent->getRenderTransform().getPosition();
Point3F focusPoint = playerPos
+ (opponentPos - playerPos) / 2;
setPosition(focusPoint, Point3F(0,0,3.14));
}
}However, the camera judders horribly. I've checked all the obvious things: focusPoint is the same on client and server, tried just simply moving the camera a constant distance each tick, and the juddering reamins.
So I'm guessing this has something to do with the camera only being moved every tick rather than every frame on the client. Am I heading in the right direction? How can I call a function every frame on the client? Or is the juddering something else entirely?
Any help much appreciated,
Ian
About the author
Designer and lead programmer on Frozen Synapse, Frozen Endzone, and Determinance. Co-owner of Mode 7 Games.
#2
For anyone else, delta.pos and delta.rot are the desired position and rotation at the end of the current tick, while delta.posVec and delta.rotVec are actually the vectors *from* the desired position to the position at the last tick. Every frame interpolateTick(F32 dt) is called on the client.
This took me a little while to understand fully: in fact, as time progresses through the tick interpolate is being called with smaller and smaller dt: 1 at the beggining and 0 at the end. So at the beggining of the tick pos = delta.pos + delta.posVec, and at the end it is delta.pos.
Apologies if that isn't too clear...
Ian
03/10/2004 (7:05 am)
Thanks Paul, you really put me on the right track and now I've fixed the juddering.For anyone else, delta.pos and delta.rot are the desired position and rotation at the end of the current tick, while delta.posVec and delta.rotVec are actually the vectors *from* the desired position to the position at the last tick. Every frame interpolateTick(F32 dt) is called on the client.
This took me a little while to understand fully: in fact, as time progresses through the tick interpolate is being called with smaller and smaller dt: 1 at the beggining and 0 at the end. So at the beggining of the tick pos = delta.pos + delta.posVec, and at the end it is delta.pos.
Apologies if that isn't too clear...
Ian
#3
03/10/2004 (9:40 am)
That's just right. Glad to see you figured it out so easily. :)
#4
Ian
03/10/2004 (11:38 am)
I still have one problem with this: if you're rotating and you go past PI and into -PI then prediction will usually go the wrong way around and cause one tick on arse-ness. Any tips on how to get around this?Ian
#5
03/10/2004 (3:41 pm)
Have it check to see which way is shorter and go that way...?
#7
The camera doesn't now judder if I move the player who is my client's player. However if either (a) another player on another computer, or (b) a player object created on my server/client machine but not controled by me, moves, then the camera judders.
However, looking at debug output, it appears the camera has the right ghosts set up. And if you look through the default camera the other player doesn't judder.
Can anyone help? I'm tearing my hair out.
Ian
03/16/2004 (4:39 am)
I have further problems:The camera doesn't now judder if I move the player who is my client's player. However if either (a) another player on another computer, or (b) a player object created on my server/client machine but not controled by me, moves, then the camera judders.
However, looking at debug output, it appears the camera has the right ghosts set up. And if you look through the default camera the other player doesn't judder.
Can anyone help? I'm tearing my hair out.
Ian
#8
if we look at tick x and tick (x+1), and we say that a player is moving from position y to y' during this tick.
Then is it true that:
On the server, the player is at y' at tick x, and
on the client, the player is at y at tick x, interpolates to y' between ticks x and (x+1), and then is at y' at (x+1).
Or, is it true that the client is always playing catch-up with the server, or is the server always playing catch-up with the client?
It appears that my problem is that the camera is taking the render transform of the control object, but the server transform of the other player. But, as shown above, I should be getting the render transform of both.
Any shedding of light would be much appreciated.
Ian
03/16/2004 (5:49 am)
Specifically:if we look at tick x and tick (x+1), and we say that a player is moving from position y to y' during this tick.
Then is it true that:
On the server, the player is at y' at tick x, and
on the client, the player is at y at tick x, interpolates to y' between ticks x and (x+1), and then is at y' at (x+1).
Or, is it true that the client is always playing catch-up with the server, or is the server always playing catch-up with the client?
It appears that my problem is that the camera is taking the render transform of the control object, but the server transform of the other player. But, as shown above, I should be getting the render transform of both.
Any shedding of light would be much appreciated.
Ian
#9
So I realised that my camera didn't need to sync it's position with the server at all: it simply needs to follow where it thinks the players are on the client. And voila, five minutes of code deletion and juddering has gone.
Ian
03/16/2004 (8:26 am)
Okay, with some help from Paul I've fixed it. Basically, it wasn't surprising the camera was juddering: the server thinks it's somewhere else to the client because the players *are* elsewhere on the client.So I realised that my camera didn't need to sync it's position with the server at all: it simply needs to follow where it thinks the players are on the client. And voila, five minutes of code deletion and juddering has gone.
Ian
#10
07/16/2007 (1:07 pm)
Ian I know this is a totally old post, but I was wondering if you still had the code handy that fixed this juddering, as I am attempting something similar. Thanks!
#11
Basically, the way around this I took was to make the camera positioning client side only. I removed the elements in packupdate/unpackupdate which set the position/rotation of the camera and made all position calculations happen client side. Unless you have security concerns, I would wholly reccomend this approach if trying to make an advanced camera.
My code would probably not be too much use to you, but if you need any more help feel free to drop into our chatroom - #determinance on irc.maxgaming.net - and I can give you any pertinent snippets.
Ian
07/16/2007 (1:40 pm)
Hey Scott.Basically, the way around this I took was to make the camera positioning client side only. I removed the elements in packupdate/unpackupdate which set the position/rotation of the camera and made all position calculations happen client side. Unless you have security concerns, I would wholly reccomend this approach if trying to make an advanced camera.
My code would probably not be too much use to you, but if you need any more help feel free to drop into our chatroom - #determinance on irc.maxgaming.net - and I can give you any pertinent snippets.
Ian
#12
07/16/2007 (4:46 pm)
Off-topic: jittering + stuttering = juddering?
Associate Paul Dana
This is the fundemental difference between the "transform" of an object and it's "render transform". The render transform is updated every rendered frame on the client. The regular transform is just what was sent from the server. The render transform is built by interpolating by the frame rate on the client. Look into where the code for Plyaer or for Vehicle sets up the "delta" information and then uses that to interpolate a client side position / rotation.
good luck