Cubic Splines

Blitz3D Forums/Blitz3D Programming/Cubic Splines

Jeremy Alessi(Posted 2004) [#1]
OK, I'm at a point where I really need this.

In my older networked games I always did a peer-peer setup and just to give the impression of smooth movement it was always good enough to just send the velocity of another player's vehicle or character to each other player. It's fine when you're watching someone else's character move around.

Now though I'm doing a real client/server setup ... one computer is computing all logic. The host is responsible for collisions, physics, ... all logic beside camera and local user input.

The game works ... but just by sending velocity computed by the host back to the joiner across the network is not enough ... well on my 56k laptop connection anyway. I'm not sure how all broadband machines or an LAN would react.

The laptop is reporting a ping of 190 ... so I think that's pretty slow. With that ping though and a 3rd person camera there's a lot of jitter as the car's position and velocity are adjusted. I also have a function to stop a vehicle if it doesn't recieve a new update within that machine's ping. That makes things better ... but still it's jittery (first person isn't quite as bad since the camera is hooked directly to the vehicle).

Anyway, I was hoping that with cubic splines things could be smoothed out another 90%. Basically though ... I need a fresh perspective on the concept of the cubic spline.

What I currently know is that you use 4 points. Something to the effect of using the last two positions to determine 2 new points. Then positioning the vehicle somewhere between these two new points. One of these new points is predicted with the velocity and one without or something.

Anyone who's got it down, I'd appreciate a good description of the implementation.


Ross C(Posted 2004) [#2]
I think the 3 points before hand are used to predict one point ahead. 3 points behind to measure acceration i believe. Doing some stuff like this myself. It's a nightmare for me. My head doesn't think to well. I've almost got it though. If i get anything, i'll post it.


AntonyWells(Posted 2004) [#3]
Told you it wasn't easy, (Physics based net) no matter hows you approach it ;)

Anyway, not sure if you ever got my cubic spline functions? If not, i'll have a look for them. Iirc you used them like,
Value#=Cubic(p1#,p2#,p3#,p4#,position#<0 to 1>) (Just repeat for all dimensions)
So...shouldn't be too hard to drop into your code or you know get the concept behind it to write your own.


Jeremy Alessi(Posted 2004) [#4]
Concept man concept ... describe to me in English. I want to understand this ... not just implement it. I just know I need to predict the movement on the joiner's machine from certain parameters.

From that little code snippet it looks like you figure out it's average acceleration or something over the last 4 points and then move the car in some a loop???

I'll look in some other places too until I find one that makes sense.


AntonyWells(Posted 2004) [#5]
Heh, that wasn't meant to be an explination of cubic splines, just showing you how the function was used.

From what I can remember(Going back six months, so do read up too, this ain't gonna be pretty ;p)

Basically, it's a first in, first out type of thing, when using cubics for multiplayer. Point 3 should be considered the active point, psudeoly speaking,
Do
   When RecievedData{
       Point2=Point3
       Point3.x=RecievedX
       Point3.y=RecievedY
       PingFrames=Frames
       Frames=0
       CubicPoint#=0
       CubicRate#=PingFrames/1.0
   
   }Else
   CubicPoint+CubicRate
   }
   Point1=-CurrentVelocity
   Point4=+CurrentVelocity
   Display.XY=Cubic(Point1,Point2,point3,point4,CubicPoint)
   Frame++
Loop

Basically, when you recieve an update, you need to know how many frames it's been since you last got one(I suggest an average rather than a 'live' number)
Now, you know on average how many actual frames pass between every update. All you have to do then is scale it within a range of 0 to 1. Done by deviding 1 by the frameCount. You then inc your cubic interpolation(sp?) the last par, by this.

Also, when you recieve an update, you feed point 3 back into point 2.(Or, better yet, feed in the current position. Then it'll never jump, it may go out of position, but it'll always smoothly go back in, rather than snap.(Well, under normal conditions, and in antMade theory.)


Jeremy Alessi(Posted 2004) [#6]
Ok, well you can get the frames that past by during multiplayer by dividing logic frames per second by 1000 milliseconds. In a 30 lfps game you have .03 frames per second. Multiply that by the ping to get how many logic frames have passed since you last recieved a message ... something like that. Or better still just capture the time you last recieved a message and get the delay by Millisecs() - lastMessage#.

So

framesPast = ( .03 * (Millisecs() - lastMessage#) )

err... anyway going to think some more about this.


Jeremy Alessi(Posted 2004) [#7]
Ok, there's a great article on Game Dev about this. How about implementation?

Currently, I'm having all the client's send their key presses to the host and then sending the physics information back to the each client. I started thinking though ... maybe it'd be best to just send key info with a full update every second.

Still, say I want to use the current system of just sending keypresses to the host. How do I apply the cubic spline to the clients cars?


Jeremy Alessi(Posted 2004) [#8]
Good article:

http://www.gamedev.net/reference/articles/article914.asp

There's this other one on Gamastura about Dead Reckoning ... it's quite a bit more complex and talks about DARPA and stuff ... pretty cool as this stuff was created for military simulations.

http://www.gamasutra.com/features/19970919/aronson_01.htm


Jeremy Alessi(Posted 2004) [#9]
Hmmm ... using just dead reckoning techniques you can smooth out the movement quite a bit. It's just a matter of keeping the car within a certain precision.