#move player using inverse transform3D

25 messages · Page 1 of 1 (latest)

violet robin
#

**context: ** I'm trying to make a vr game where the player moves in the opposite direction of the controller when grabbing something (position and rotation), which makes it look like you're dragging yourself along.

problem:

func _physics_process(delta):
    if grab_component.get_just_grabbed():
        grab_xform = hand.global_transform
        
    if grab_component.is_grabbing():
        var relative_xform = hand.global_transform * grab_xform.affine_inverse()
        player.global_transform *= relative_xform.affine_inverse()

the seemingly works the first few seconds but after sometime everything starts to jitter and shearing occurs, so the transform is messed up but I don't know why. (see video)

violet robin
#

I think there is some kind of slight incremental error (could be my fault or floating point errors that causes the player's transform to get slightly distorted which in turn causes all it's children's transforms to get slightly distorted (including the hand transform). The player new transform is calculated using the hand's transform so it gets worse and worse.

#

player.global_transform = hand.transform.inverse()

just setting the player's transform to the inverse of the hand's transform works without any jitter/glitches

#

but the transform is getting set, not added so you can't move around you just move in the opposite direction of you hand

violet robin
#

also: I feel like I should be using delta in some way because we're applying something over time

static river
#

If you only care about the position, and not rotation or scale, then it might be best to only work with position, rather than the entire transform

static river
violet robin
#

but trying to add rotation is the problem

#

I'm starting to think it's floating point errors. Orthonormalizing prevents the skewing but still causes weird stuff to happen

static river
#

Hm. You could try applying the position and rotation separately, and still avoiding the transform?

#

Just trying to figure out if something weird is happening with the transform or not..

violet robin
#

I've tried using quaternions to rotate the player but to no avail, the same problem

#

this is the code for it btw: (only rotation)

    
    if grab_component.get_just_grabbed():
        grab_xform = hand.global_transform
        
    if grab_component.is_grabbing():
        
        var rotation_offset = hand.global_basis.get_rotation_quaternion().inverse() * grab_xform.basis.get_rotation_quaternion()
        player.global_basis = Basis(player.global_basis.get_rotation_quaternion()*rotation_offset).orthonormalized()
        ```
static river
#

If the issue is with compounding errors from floating points, then maybe you could store the transform of the hand at the moment that it grabs, and then move the player based on the difference from the initial grab transform?

#

That should give you a similar effect, but wouldn't suffer from compounding error

violet robin
#

ok I'll try that

violet robin
#

tysm I found a solution!!!

static river
#

!!

#

What ended up working?

violet robin
#

this took embarrassingly long to find but here it is:

class_name MoveComponent
extends Node

@export var player:CharacterBody3D
@export var hand:XRController3D
@export var grab_component: GrabComponent

var grab_xform: Transform3D
var player_start_xform: Transform3D

func _physics_process(delta):
    
    if grab_component.get_just_grabbed():
        grab_xform = hand.transform
        player_start_xform = player.global_transform
        
    if grab_component.is_grabbing():
        var difference = grab_xform * hand.transform.inverse()
        player.global_transform = player_start_xform * difference

#

the rotation is a bit nauseous tho

static river
#

Yeah, I notice that most VR games with a system like this don't do rotation, likely for that reason.

#

Either way, glad you got it working!