Game Development Community

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:

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

#1
03/10/2004 (5:25 am)
You have to look into and understand how the client prediction works in torque. Take a look at a class like the Player class or a Vehicle class. You will see that when the client receives a "move" then a "delta" is setup for that move tha describes how the client should move (or rotate) from this server frame to the next.

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
#2
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
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...?
#6
03/11/2004 (3:01 am)
/me boggles at his own incompetence.

Cheers Ben!

Ian
#7
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
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
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
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?