0
\$\begingroup\$

Here is the code I'm starting from:

func orientation_follow(state, current_basis : Basis, target_basis : Basis):
    var delta : Basis = target_basis * current_basis.inverse();

    var q = Quat(delta);
    var axis = Vector3(q.x, q.y, q.z);

    if (axis.length_squared() > 0.0001):  # bullet fuzzyzero() is < FLT_EPSILON (1E-5)
        axis = axis.normalized();
        var angle = 2.0 * acos(q.w);
        state.set_angular_velocity(axis * (angle / (state.get_step())));
    else:
        state.set_angular_velocity(Vector3(0,0,0));

The basis is the direction in which each vector of the object has been rotated. That is inverted and multiplied by the basis of the target object (in this case, the player's motion controller) to get the delta rotation from the object to the controller. That delta gets converted to a quaternion, from which its axis is derived and normalized before multiplying the arccosine of the quaternion's z coefficient by 2 to get the angle and finding the product of the angle and that axis (divided by delta time, which I suppose smooths the rotation a bit), setting the angular velocity per how RigidBody objects are meant to be interacted with in Godot.

At least, that's what I think is going on.

The problem is, every time you pick up an object, it essentially snaps to the rotation of the controller, because the function is interpolating the rotation of the object to the rotation of the controller every frame. So if you're trying to turn something upside-down, you have to turn your controller all the way around, instead of picking it up, putting it down partially rotated, then using your other controller to complete the rotation.

What I would like to do is get the difference in rotation in the controller between the last frame and the current frame, then apply that difference to the held object each frame, but nothing I've tried over the last few hours seems to work. The end goal is for an object to keep its rotation when initially picked up, but to rotate the same amount as the controller while held, rather than immediately snapping to the orientation as the controller as soon as it gets picked up.

\$\endgroup\$
2
\$\begingroup\$

Turns out the solution to the fundamental problem is to avoid the complicated math and just use an appropriately-configured HingeJoint. When a player grabs an object, set node A to a kinematic body child node of that controller, and set node B to the object being grabbed. Set both paths to empty strings when they let go.

The actual result is a little wonky, but today, I choose to leave tomorrow's problems for tomorrow's me.

hinge joint properties

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.