Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct way to change a body's position and orientation? #215

Open
josephrocca opened this issue Jul 27, 2015 · 13 comments
Open

Correct way to change a body's position and orientation? #215

josephrocca opened this issue Jul 27, 2015 · 13 comments

Comments

@josephrocca
Copy link

I want to change a body's position and orientation and reset all of its dynamic properties like velocity, angular velocity, and anything else that affects the simulation. Currently I use the following (where x, y, z is my new position and a, b, c, w is my new quaternion):

body.position.set(x, y, z);
body.quaternion.set(a, b, c, w);
body.velocity.set(0, 0, 0);
body.angularVelocity.set(0, 0, 0);

I'm wondering whether this is the most efficient way to do it and/or whether I've missed anything?

Thanks!

@schteppe
Copy link
Owner

Hi,

For many cases, your code should be fine. If you use interpolation, sleeping, or if you have custom force fields, you might want to add some more stuff. Here's some draft code to reset the (hopefully) whole state.

// Position
body.position.setZero();
body.previousPosition.setZero();
body.interpolatedPosition.setZero();
body.initPosition.setZero();

// orientation
body.quaternion.set(0,0,0,1);
body.initQuaternion.set(0,0,0,1);
body.previousQuaternion.set(0,0,0,1);
body.interpolatedQuaternion.set(0,0,0,1);

// Velocity
body.velocity.setZero();
body.initVelocity.setZero();
body.angularVelocity.setZero();
body.initAngularVelocity.setZero();

// Force
body.force.setZero();
body.torque.setZero();

// Sleep state reset
body.sleepState = 0;
body.timeLastSleepy = 0;
body._wakeUpAfterNarrowphase = false;

I've been wondering if this code should be in a method, but I'm not sure how... The position and interpolation stuff could fit in a .teleport(position, quaternion) method, but that would not cover velocity or force.

@josephrocca
Copy link
Author

Thanks! A teleport method would be fantastic - maybe with an option or two to handle the dynamic stuff?

@josephrocca josephrocca changed the title Correct way to change a bodies position and orientation? Correct way to change a body's position and orientation? Jul 28, 2015
@ioquatix
Copy link

+1

@ioquatix
Copy link

In addition, since I'm writing a game where I need to do key-frame physics synchronisation, it would be great to have a serialise and deserialise method which generates a JSON compatible array which clones exact object state so the physics can be copied from server to client.

@ioquatix
Copy link

Okay, yeah, this is causing me problems. Trying to sync the state between the server and client is causing issues. If I sync all these values, should that (in theory) work?

@ioquatix
Copy link

Here is a really quick hack to see if this would fix sync bugs I'm having.. doesn't seem to be working well.. any ideas?

CANNON.Body.prototype.serialize = function() {
    return [
        // Position
        this.position.x, this.position.y, this.position.z,
        this.previousPosition.x, this.previousPosition.y, this.previousPosition.z,
        this.interpolatedPosition.x, this.interpolatedPosition.y, this.interpolatedPosition.z,
        this.initPosition.x, this.initPosition.y, this.initPosition.z,

        // Orientation
        this.quaternion.x, this.quaternion.y, this.quaternion.z, this.quaternion.w,
        this.previousQuaternion.x, this.previousQuaternion.y, this.previousQuaternion.z, this.previousQuaternion.w,
        this.interpolatedQuaternion.x, this.interpolatedQuaternion.y, this.interpolatedQuaternion.z, this.interpolatedQuaternion.w,
        this.initQuaternion.x, this.initQuaternion.y, this.initQuaternion.z, this.initQuaternion.w,

        // Velocity
        this.velocity.x, this.velocity.y, this.velocity.z,
        this.initVelocity.x, this.initVelocity.y, this.initVelocity.z,
        this.angularVelocity.x, this.angularVelocity.y, this.angularVelocity.z,
        this.initAngularVelocity.x, this.initAngularVelocity.y, this.initAngularVelocity.z,

        this.force.x, this.force.y, this.force.z,
        this.torque.x, this.torque.y, this.torque.z,

        this.sleepState,
        this.timeLastSleepy,
        this._wakeUpAfterNarrowphase
    ];
}

CANNON.Body.prototype.deserialize = function(data) {
    this.position.set(data[0], data[1], data[2]);
    this.previousPosition.set(data[3], data[4], data[5]);
    this.interpolatedPosition.set(data[6], data[7], data[8]);
    this.initPosition.set(data[9], data[10], data[11]);

    // orientation
    this.quaternion.set(data[12], data[13], data[14], data[15]);
    this.previousQuaternion.set(data[16], data[17], data[18], data[19]);
    this.interpolatedQuaternion.set(data[20], data[21], data[22], data[23]);
    this.initQuaternion.set(data[24], data[25], data[26], data[27]);

    // Velocity
    this.velocity.set(data[28], data[29], data[30]);
    this.initVelocity.set(data[31], data[32], data[33]);
    this.angularVelocity.set(data[34], data[35], data[36]);
    this.initAngularVelocity.set(data[37], data[38], data[39]);

    // Force
    this.force.set(data[40], data[41], data[42]);
    this.torque.set(data[43], data[44], data[45]);

    // Sleep state reset
    this.sleepState = data[46];
    this.timeLastSleepy = data[47];
    this._wakeUpAfterNarrowphase = data[48];
}

@schteppe
Copy link
Owner

@ioquatix I made a serializer for p2.js, but I removed it after a while. It's a bit of work to maintain it, and in the end I realized that it's not being used in practice. You always want a custom file format for whatever you are building, so the only value in a serializer is just the knowledge how to serialize and deserialize a physics state.

Synchronizing those values should probably work for one given point in time. Do you use client side prediction or any similar algorithm? (This is a difficult problem you know - even the big game titles avoid this :P)

@ioquatix
Copy link

@schteppe So we are using Node.js and running the physics both server and client side. The idea is to send keyframe sync but in general the two simulations run independently, but I'm seeing some pretty wonky behaviour, but most of the time it is working "reasonable". I've had a lot of issues with player movement.. This is a work in progress :)

I'd really appreciate if you have some time to check it out:

https://github.com/GameMechanicsSociety/warehouse

@ioquatix
Copy link

I've just committed to the development branch, a commit that only does server side physics and has a client side update rate of 15 FPS., just FYI.

@ioquatix
Copy link

Sorry to bother you but one more issue that comes up is that sometimes player cannot move. I wonder if they got stuck in the ground plane. I tried to add a small +ve Z value in applyImpulse but I'm not sure if that helps or not.

@schteppe
Copy link
Owner

@ioquatix All right. It should work perfectly for a single body without contacts. If you have contacts you should probably not touch the position or velocity. Maybe you can add a force toward the authoritative server position, and if the player is way off, teleport?

I never got client/server physics sync working - I've always avoided it because it's a really difficult problem.

Maybe you are interested in how UDK does it. For small corrections they add an impulse toward the server position. https://udn.epicgames.com/Three/NetworkingOverview.html

15FPS is probably too bad for rigid body physics. Probably works for game-specific physics like minecraft but for general rigid body simulation, probably not. Try this link, set FPS to 15 and drag the ragdoll around: https://schteppe.github.io/p2.js/demos/ragdoll.html

@top-kat
Copy link

top-kat commented Mar 4, 2017

+1 for teleport method :)

@MrSonicMaster
Copy link

+1 again for a teleport method. It would be great if the teleport method would not only handle position/rotation and interpolation for both, but also to change the direction of forces/impulses that are currently applied to move in the direction of the new rotation. That would be great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants