Networking physics simulation

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Re: Networking physics simulation

JoeJ wrote:Oh, i have missed this final post. Did you get it working meanwhile?

Can't remember anything or why i have commented out the division at the moment.
You could post your own code so i can verify...

I can confirm however controlling with torque works as good as with force. I do not think ground friction is the problem...

Sorry for another late reply. i was without a pc and had some other things to attend to last month, but i can now show my implementation.

A big issue here is, that it won't rotate it to exact angle, and when i do multiple corrections via mouse clicks, the calculated torque seems to go nuts, and just produces large, violent rotations.

https://youtu.be/B60es5E72DA

Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

Only the master / server computer should calculate collision.

You are making it way too complicated.
JoshKlint

Posts: 74
Joined: Sun Dec 10, 2017 8:03 pm

Re: Networking physics simulation

No idea what's wrong, but i'll bundle up all the angular code to a single snippet:

Code: Select all
`quat targetOrientation = server orientation, or average of all clients, or whateverquat currentOrientation = BodyGetOrientation (body);quat rotationFromCurToTarget; // calculate shortest arc rotation between the two...{   quat qA = currentOrientation   quat qB = targetOrientation;   quat q; // temp   if (qA.Dot(qB) < 0.0f)    {      q[0] = qA[0]; q[1] = qA[1]; q[2] = qA[2];      q[3] = -qA[3];   }   else   {      q[0] = -qA[0]; q[1] = -qA[1]; q[2] = -qA[2];      q[3] = qA[3];   }            rotationFromCurToTarget = qB * q; // EDIT: Newton has opposite multiplication order, would be q * qB}vec axis; float angle;rotationFromCurToTarget.ToAxisAndAngle(axis, angle);vec targetAngVel = axis * angle / timestep; // to rotate to target in one stepvec currentAngVel = BodyGetOmega(body);float mass, Ixx, Iyy, Izz; BodyGetMassAndInertia(mass, Ixx, Iyy, Izz);float duration = timestep * 10; // give it more time than one step to prevent overshootvec torque = (targetAngVel - currentAngVel) / duration;torque = matrix.Unrotate (torque); // rotate to local body spacetorque[0] *= Ixx;torque[1] *= Iyy; // apply nonuniform scale caused by inertiatorque[2] *= Izz;torque = matrix.Rotate (torque); // rotate back to global space// the above could be compacted to a single matrix multiplication but i don't know yet if Newton exposes thisBodyAddTorque (body, torque);`

I assume the most likely place for a bug is the rotation between body and target, so the section 'calculate shortest arc rotation between the two'.

Notice that i use quaternions in xyzw order, but Newton returns them in wxyz order, so you may need to change the indices (i already reorder in anbstraction layer and i assume returned xyzw here)

Likely you have your own quat stuff that gives rotation between two orientations, but be sure the shortest arc is chosen using the dot product check, which is usually up to the users of quat libraries.

Hope this helps, otherwise post your code...

JoshKlint wrote:Only the master / server computer should calculate collision.

You are making it way too complicated.

I don't think we add compliactions here. There are multiple physics simulations running, but syncing them is not more complicated than syncing input and ouput i would say.

But i'm not experineced with netcode.

However, if each client runs it's own sim, there is no latency issue and no additional 'layer of illusions' presented to the user. I think its a very interesting take on the problem...

JoeJ

Posts: 1156
Joined: Tue Dec 21, 2010 6:18 pm

Re: Networking physics simulation

JoshKlint wrote:Only the master / server computer should calculate collision.

You are making it way too complicated.

There must be an misunderstanding, that is exactly what i am doing, what this discussion is about, is how to move bodies to their correct (masterserver) positions and have them move in good way.

JoeJ: I'll have that checked, i'll post my version of code that i use too.
Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

JernejL wrote:There must be an misunderstanding, that is exactly what i am doing, what this discussion is about, is how to move bodies to their correct (masterserver) positions and have them move in good way.

I see, so the reason you run physics on clients is to eliminate lag or dependency on high frequency network?

I think the idea is interesting also at larger scales, e.g. thousands of players in a common huge world. Each client would simulate it's neighborhood, and the server would only manage to keep overlaps consistent (and game logic like damage and health of course.)

Problems like a body ending up on both sides of a wall on multiple clients would need special care and decision from the server side, e.g. choosing the side that agrees to what more players have in their view at the moment.

JoeJ

Posts: 1156
Joined: Tue Dec 21, 2010 6:18 pm

Re: Networking physics simulation

Exactly the idea - this is mainly to eliminate lag. So basically the server runs the master simulation, which every client receives, this is how the client gets it's remote players.

Client runs a simulation locally, and sends it to sever - this allows for much better interpretation of his movements locally (no remote server lag for movement and driving), server gives client some slack up to until his movement is considered legal (to prevent cheating) - at that point, server starts ignoring client updates until it receives entire the server's enforced legit "update". So, with reasonable pings you will get a really good response (tested up to 300ms so far), but with high ping the server will put you back in your place.

So if a client crashes into a wall, his physical collision can be much better than one replicated from the server.

The only issue i have is, moving the remote server bodies to correct orientation and location via forces and torque, in order to have the client respond to remote body movement correctly.

This is my translation of your previous code, i use newton with freepascal so this is in pascal, but it's practically identical:

Code: Select all
`function get_torque_towards_rotation_target(const newtonbody: Pnewtonbody; const targetMatrix: TMatrix4f; const timestep: single): Vector;var    rotation, qA, qB, q: TQuaternion;    bodymass: single; ixx, iyy, izz: single;   //duration: Single;    axis, curAngvel: Vector;    targetAngvel: Vector;    angle: single;    torque: Vector;    currentMatrix: TMatrix4f;begin    NewtonBodyGetMass(newtonbody, @bodymass, @ixx, @iyy, @izz);    NewtonBodyGetMatrix(newtonbody, @currentMatrix);    //duration := timestep * 1; // duration until we hit the target    // Doing this for orientation we first calculate the rotation from current to target orientation:   qA := currentMatrix.ToQuaternion();   qB := targetMatrix.ToQuaternion();   if (qA.Dot(qB) < 0) then begin // make sure we choose the shortest arc (usually people use inverse() to make this more intuitive)      q.arr[0] := qA.arr[0]; q.arr[1] := qA.arr[1]; q.arr[2] := qA.arr[2];      q.arr[3] := -qA.arr[3]; // i store W in the 4th element (xyzw order); Julio in the first (wxyz) !   end else begin      q.arr[0] := -qA.arr[0]; q.arr[1] := -qA.arr[1]; q.arr[2] := -qA.arr[2];      q.arr[3] := qA.arr[3];   end;   rotation := qB * q; // with Julios mathlib you'd need to reverse this: rotation = q * qB !    // convert the resulting rotation to axis and angle:    rotation.ToAxisAndAngle(axis, angle);    // convert axis and angle to rotation vector, which encodes angle in the vector length:    targetAngvel := axis * angle;    NewtonBodyGetOmega(newtonbody, @curAngvel);    // may be still too aggressive - eventually try to smooth it:  targetAngvel = targetAngvel * 0.1 + curAngvel  * 0.9;    //// vec force = (targetLinvel - curLinvel) * mass;    // instead of multiplying by uniform mass, we need to do a nonuniform scale    // in local space where inertia is defined:    torque := (targetAngvel - curAngvel); // duration;    torque.MultiplyComponents(timestep);    torque := currentMatrix.Unrotate(torque);    torque.components[0] *= Ixx;    torque.components[1] *= Iyy;    torque.components[2] *= Izz;    torque := currentMatrix.RotateVector(torque);    // add and adjust this if it seems to work til here: torque.SetMaxLength(someConstant);    result:= torque;end;`

With this, i then just call NewtonBodySetTorque to zero it, & NewtonBodyAddTorque with the result
Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

I think there is this bug: torque.MultiplyComponents(timestep);

should be division instead multiplication, so: torque.MultiplyComponents(1 / timestep);

But this would do the whole correction in one step, so angle is correct at next step but also there will be velocity and the angle will overshoot in the following step.

Likely what you want is a longer duration than the timestep so angle can settle at the target, eg 10 times the timestep: torque.MultiplyComponents(1 / (timestep * 10));

If it still does not work don't forget to try reversing multiplication order for qB * q.

JoeJ

Posts: 1156
Joined: Tue Dec 21, 2010 6:18 pm

Re: Networking physics simulation

JoeJ wrote:I think there is this bug: torque.MultiplyComponents(timestep);

should be division instead multiplication, so: torque.MultiplyComponents(1 / timestep);

But this would do the whole correction in one step, so angle is correct at next step but also there will be velocity and the angle will overshoot in the following step.

Likely what you want is a longer duration than the timestep so angle can settle at the target, eg 10 times the timestep: torque.MultiplyComponents(1 / (timestep * 10));

If it still does not work don't forget to try reversing multiplication order for qB * q.

I've tried the 1/timestep and after the change, it did nothing (didn't change object orientation at all), i tried many values for timestep, and it also didn't do any changes.

I also tried reversing 1B * q and that also didn't seem to do any change, the main issue does seem to be, that the problem occurs when the body is already turning / has omega.

I've stuck this into code where the NewtonBodyGetOmega vall is originally:

Code: Select all
`    NewtonBodySetOmega(newtonbody, @nullvector);    curAngvel:= nullvector;`

This seems to improve things, while it just nullifies old omega, which might make rotations more abrupt, this seems to partially work - rotation is approximately correct with minor error (which i think can still be attributed to ground friction). - so whatever the issue is, it's related to how curAngvel is added to final torque.

Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

Sounds you are tapping around in a dark room of uncertainty.

I would do two things:
Instead of using torque, change body angular velocity directly to eliminate one source of error. After this works, figure out the torque.

If it still does not work (i guess so), make an independent test case with a single body floating in space without gravity. Visualize some kind of target orientation and proof the math until you can control the body to reach the target robustly. First using ang.vel. only, and then with torque.

I can not draw any conclusions from the video because the target orientation is not shown. Visualizing such stuff really helps...

JoeJ

Posts: 1156
Joined: Tue Dec 21, 2010 6:18 pm

Re: Networking physics simulation

The target orientation is always "towards the cursor", sorry for not explaining this before, what i am doing is clicking, and clicking sets rotation via torque method towards cursor.
Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

Ok. I remember when doing things wrong, ignoring current velocity seemed helped me too, but this looks correct:

torque := (targetAngvel - curAngvel); // duration;

If you think of it this just means 'if current already is the target, do nothing'.
I'm still unable to spot the bug. Suspecting quaternion code still the most. You could construct a testcase with a wheel and joint, and proof your math just by using angles but no 3D rotations to narrow it down. (It would end up with exact the same math as the linear part then)

I have suggested Julio to change the quat memory layout to more common xyzw - if he does this change the array indices would need to be changed accordingly eventually.

JoeJ

Posts: 1156
Joined: Tue Dec 21, 2010 6:18 pm

Re: Networking physics simulation

JoeJ wrote:Ok. I remember when doing things wrong, ignoring current velocity seemed helped me too, but this looks correct:

torque := (targetAngvel - curAngvel); // duration;

If you think of it this just means 'if current already is the target, do nothing'.
I'm still unable to spot the bug. Suspecting quaternion code still the most. You could construct a testcase with a wheel and joint, and proof your math just by using angles but no 3D rotations to narrow it down. (It would end up with exact the same math as the linear part then)

I have suggested Julio to change the quat memory layout to more common xyzw - if he does this change the array indices would need to be changed accordingly eventually.

I'm not using julio's quaternion math library, so it's not a memory layout issue here.
I think i can work with NewtonBodySetOmega workaround, it would still all enable me to reach what i need, and when i want to is just set new omega & velocity to match a new orientation.

Ability to calculate this inside physics engine as a feature would quite help in synchronizing or moving bodies like this.
Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

I think i can work with NewtonBodySetOmega workaround

Yes, if you get this working the way you want but there are sideeffects, you can always switch to using torque later (which really should work with the same behavior but without the sideeffects).

However, looking at Mishos topis, maybe this would be another option:

Code: Select all
`void dgBody::ApplyImpulsePair (const dgVector& linearImpulseIn, const dgVector& angularImpulseIn, dgFloat32 timestep){   m_impulseForce += linearImpulseIn.Scale(1.0f / timestep);   m_impulseTorque += angularImpulseIn.Scale(1.0f / timestep);   m_sleeping   = false;   m_equilibrium = false;   Unfreeze ();}`

And maybe the your problem comes from falling asleep but not from wrong torque math as we assume.

JoeJ

Posts: 1156
Joined: Tue Dec 21, 2010 6:18 pm

Re: Networking physics simulation

I got this integrated and tested well, and i wish to share this really positive result: this is final work (with pre-zeroed omega workaround).

The red car that comes into view at approx middle of the video is remote synced and is interpolated on client only in physics engine (no visual fakery / tricks) - the movement is so smooth it's hard to see it's not on the same client.

Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Networking physics simulation

This video is fully remote gameplay - Except for main player, everything else is synced from master server.

There are some glitches but mostly with visual look and particles, physics / sync looks great.

Later i also turn on rendering of data that is being received from server, and how that correlates with local simulation positions.

Help improving the Newton Game Dynamics WIKI

JernejL

Posts: 1521
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

PreviousNext