How to use interpolation functions for multiplayer?

Post Reply
DrenDran
Posts: 6
Joined: Thu Aug 31, 2017 10:08 pm

How to use interpolation functions for multiplayer?

Post by DrenDran »

Hey there. I've been making a multiplayer game with OpenGL for graphics and Bullet as the physics engine. The server and client both have physics simulations running, and the server occasionally (every second or so) sends the position, rotation, and angular and linear velocities of each block to each of the clients. I've tested this over an internet connection (with relatively low latency) and it works well enough. Here's a video:
https://www.youtube.com/watch?time_cont ... fbXkeMh_aU

What I'm wondering though is whether or not I can find a way to stop the occasional jitteryness of having blocks continuously teleport a little distance from where they currently are. Is there a way that when the server sends the new position to the client, the client can 'ease' the block over to the new position? Like if the server sends a request to teleport a block, how do I make the client make the block fly over there rather than just instantly teleport?

I've tried replacing the calls of 'setWorldTransform' with 'setInterpolationWorldTransform' but all that happens is when the server tries to move a block the block kind of just spazzes out or starts floating slowly. I've heard you have to call 'stepSimulation' in your rendering loop without a second argument, but I already call stepSimulation every frame without issue, and adding further calls (with or without a second argument) only makes things worse. How do I actually go about using these functions?

For reference by game logic looks a bit like this:

Code: Select all

while(playing)
{
//take input
walkDir = 0,0,0
if(wKeyDown)
walkDir += sin(yaw),0,0
if(sKeyDown)
walkDir += -sin(yaw),0,0
//etc.
player->rigidBody->setLinearVelocity(player->reigidBody->getLinearVelocity() + walkDir)

//process server commands
if(addNewObject)
{
rigidBody = new rigidBody
rigidBody.setAttributes(etc)
rigidBodies.push_back(rigidBody)
}
if(setObjectPos)
{
btTransform tmp;
btVector3 tmp1,tmp2;
memcpy(&tmp,serverPacket,size)
memcpy(&tmp1,serverPacket+offset,size)
memcpy(&tmp2,serverPacket+offset,size)
rigidBody[index]->setTransform(tmp);
rigidBody[index]->setLinearVelocity(tmp1)
rigidBody[index]->setAngularVelocity(tmp2)
}

//Physics simulation
delta = getMiliseconds()-lastFrame
lastFrame = getMiliseconds()
world->stepSimulation(delta/60.f,10)

//Render
cameraPos = player->rigidBody->getWorldTransform().getOrigin()

for(rigidBodies.size())
{
rigidBody[a]->getMotionState()->getWorldTransform(transform);
btScalar m[16];
transform.getOpenGLMatrix(m);
renderModelAt(m);
}
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: How to use interpolation functions for multiplayer?

Post by drleviathan »

One idea that comes to mind is you could make an Action whose job is to interpolate a list of objects from their pointA to pointB in some short time period. The Action should probably set the objects collisionless while moving them since otherwise they may try to push right through other objects. When an object reaches its pointB the Action would set its final position+velocity correctly, re-enable collisions, and remove it from the list.

To make an Action you derive from btActionInterface and implement the pure virtual updateAction() method to perform the interpolations you need. You then would add it to the world using btDiscreteDynamicsWorld::addAction(). Bullet's API guarantees that each Action's updateAction() method will be called once per substep.
Post Reply