Skip to main content
GameDev.net gamedev.net
🔒 Locked

Entity Position Interpolation Code

Started by DarkDemon Apr 6, 2011 at 3:44 PM 4 replies 3.7k views
Original Post
DarkDemon
DarkDemon
Hello all,


I was wondering if anyone is familer with the following http://www.mindcontrol.org/~hplus/epic/ entity interpolation code?

I have a few questions in relation to it:

1. Given the following extract http://pastebin.com/hab0chaU, could you explain the relevancy of the ReadPosition() call in the addSample function? do the values get modified in anway? I'm just not 100% on why this call is there, some clarification would be great. I'm still learning this interpolation process.

2. In the following function why is the X position the only one being passed in? instead of both x,y?

void DeliverPacket(Packet const &packet, double now)
{
intPos.AddSample(packet.time, now, &packet.pos.x);
}

Apologies for my naivety, I'm not awfully familer with C++ or a few of these concepts, any clarification would be greatly appreicated.


Thanks!
P.S I did pm hplus0603, the author of this sample, but yet had no response, however I can see he posts in this section quite a lot so if you're reading hplus0603, I'd be grateful if you could answer these questions, many thanks!
hplus0603
hplus0603

1. Given the following extract http://pastebin.com/hab0chaU, could you explain the relevancy of the ReadPosition() call in the addSample function? do the values get modified in anway? I'm just not 100% on why this call is there, some clarification would be great. I'm still learning this interpolation process.


First, thanks for asking in the forum where everyone can benefit from the answer!

Second, the reason to read the position is because the code is updating the "snap position" for where to start extrapolating from. The extrapolated position may not be the same as the position you actually get from the server, but to avoid discontinuities, the code uses the extrapolated position as the next baseline, rather than "Jumping" the start position to the new sample. Instead, it calculates where the new sample plus the previous sample say the player will be in the future, and makes the extrapolator aim for that point at some small distance into the future.




2. In the following function why is the X position the only one being passed in? instead of both x,y?
intPos.AddSample(packet.time, now, &packet.pos.x);
[/quote]

Actually, it passes a pointer to float, where that pointer will be assumed to contain as many floats as contained in the interpolated value. Because the layout of the struct is (x,y) and the interpolator is configured to use two values, it will actually read both the X and the Y values, using the C/C++ "pointers and arrays are very similar" semantics.
enum Bool { True, False, FileNotFound };
DarkDemon
DarkDemon

[quote name='DarkDemon' timestamp='1302104675' post='4795074']
1. Given the following extract http://pastebin.com/hab0chaU, could you explain the relevancy of the ReadPosition() call in the addSample function? do the values get modified in anway? I'm just not 100% on why this call is there, some clarification would be great. I'm still learning this interpolation process.


First, thanks for asking in the forum where everyone can benefit from the answer!

Second, the reason to read the position is because the code is updating the "snap position" for where to start extrapolating from. The extrapolated position may not be the same as the position you actually get from the server, but to avoid discontinuities, the code uses the extrapolated position as the next baseline, rather than "Jumping" the start position to the new sample. Instead, it calculates where the new sample plus the previous sample say the player will be in the future, and makes the extrapolator aim for that point at some small distance into the future.


[/quote]



Thanks for the explanation.


[quote name='DarkDemon' timestamp='1302104675' post='4795074']
2. In the following function why is the X position the only one being passed in? instead of both x,y?
intPos.AddSample(packet.time, now, &packet.pos.x);


Actually, it passes a pointer to float, where that pointer will be assumed to contain as many floats as contained in the interpolated value. Because the layout of the struct is (x,y) and the interpolator is configured to use two values, it will actually read both the X and the Y values, using the C/C++ "pointers and arrays are very similar" semantics.
[/quote]

Oh I see, I assumed only the X position was being passed in, I never knew pointers behaved in such a manner if wrapped around a struct, that's very handy

Thank you again. I shall post again I have any further queries.
DarkDemon
DarkDemon
I have one further question in relation to time.

I'm using Java coupled with the light weight java game library. I have the extrapolator pretty much coverted now, but need to resolve the issue of time.

double GetRealTime()
{
long long now;
QueryPerformanceCounter((LARGE_INTEGER *)&now);
// work around dual-core bug
if (now < lastRead) {
now = lastRead + 1;
}
if (now - lastRead > maxDelta) {
// don't advance time too much all at once
baseReading += now - lastRead - maxDelta;
}
lastRead = now;
return (now - baseReading) * tickMultiply;
}[/quote]



To get time I use the following http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_4_%28Timing%29

This gives me a long, given my context what would be the most suitable way to producing the double value? should I do the same as the above but omit the work around bug for duel core machines? This seems to be the only sticking point at the moment. I'm looking for the same sort of solution that I easily replicate, at the moment I get strange results based on using longs.
hplus0603
hplus0603

This gives me a long, given my context what would be the most suitable way to producing the double value?


Cast it to double?

There are two functions on that page, though -- both truncate time to milliseconds, which is just barely good enough.
If you have a nanoTime() function, you might want to do something like:

return (double)System.nanoTime() / 1000000000.0; // convert to double

This returns real seconds, too, although the interpolator doesn't care about the unit, as long as you're consistent.
enum Bool { True, False, FileNotFound };
DarkDemon
DarkDemon

[quote name='DarkDemon' timestamp='1302126225' post='4795233']
This gives me a long, given my context what would be the most suitable way to producing the double value?


Cast it to double?

There are two functions on that page, though -- both truncate time to milliseconds, which is just barely good enough.
If you have a nanoTime() function, you might want to do something like:

return (double)System.nanoTime() / 1000000000.0; // convert to double

This returns real seconds, too, although the interpolator doesn't care about the unit, as long as you're consistent.
[/quote]

Many thanks,

I used nanoTime, which works perfectly. I've now got this working over multiple machines. The only thing I've tweaked is the clients sync there clocks with the server when they connect. Other than that, works great. Thanks again!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.