3D model warps when rotating using basis.z

Godot Version

v. 4.0.3

Question

So I’m learning to program different types of cameras for 3D games, but I’m having trouble. Many games nowadays use an over-the-shoulder camera where the mouse input controls the direction the camera is facing, not the camera itself. I’ve already been able to program the over-the-shoulder kind of camera, but I’m looking to replicate early 3D camera physics - where going forward means moving away relative to the camera. Whereas I originally had an input function to have the camera dictate the rotation of the model in real time, I would like the camera to rotate around the model and only have that rotation affect it when a directional action is pressed, and I have managed to achieve this using the get_global_transform().basis.z. The problem is that the rotation completely skews the model and I have no idea how to fix it. When facing the left and right (-X and X), the model becomes incredibly thin, and looks unnatural at any rotation angle. How do I perform these rotations without warping the model?

extends RigidBody3D

var mouse_sensitivity := 0.001
var twist_input := 0.0
var pitch_input := 0.0

@onready var animation_player = $“medgestandingriggedmapping3+animation2/AnimationPlayer”
@onready var twist_pivot := $TwistPivot
@onready var pitch_pivot := $TwistPivot/PitchPivot

func _ready() → void:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
animation_player.play(“Idle”)

func _process(delta: float) → void:
var input := Vector3.ZERO
var vector3_f = $TwistPivot/PitchPivot/Camera3D.get_global_transform().basis.z
input.x = Input.get_axis(“move_left”, “move_right”)
input.z = Input.get_axis(“move_forward”,“move_back”)

if Input.is_action_just_pressed("move_forward"):

#This line here vv causes models to warp
$“medgestandingriggedmapping3+animation2”.basis.z = -vector3_f
if animation_player.current_animation != “Running”:
animation_player.play(“Running”)

if Input.is_action_just_released("move_forward"):
	if animation_player.current_animation == "Running":
		animation_player.play("Idle")

apply_central_force(twist_pivot.basis * input * 1200.0 * delta)

if Input.is_action_just_pressed("ui_cancel"):
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
if Input.is_action_just_pressed("Click"):
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	
twist_pivot.rotate_y(twist_input)
pitch_pivot.rotate_x(pitch_input)
pitch_pivot.rotation.x = clamp(pitch_pivot.rotation.x,
	deg_to_rad(-30),
	deg_to_rad(30)
)
twist_input = 0.0
pitch_input = 0.0

func _unhandled_input(event: InputEvent) → void:
if event is InputEventMouseMotion:
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
twist_input = - event.relative.x * mouse_sensitivity
pitch_input = - event.relative.y * mouse_sensitivity

I didn’t read any code because it’s not formatted.

But I will say this. The basis matrix handles rotation and scale. If you modify one basis vector it may no longer be orthonormal. And will begin to “skew”.

I would use the built in functions for basis manipulation over manipulating it manually.
If one basis vector changes at least one other basis vector also needs to change to remain “square”. ( Orthonormal)

I suppose that’s my issue. I’m having trouble with the difference between built-in functions and ones that manipulate objects manually, what is the advantage of using built-in functions? And what would the syntaxe be to get the built-in basis function? Thank you so much for your help!