The object I want to rotate is a MeshInstance. thanks.
How do a rotate an object around a point?
Some resources:
- How to rotate a Spatial node around an axis at a given point in space? (Reddit)
- Rotate around a fixed point in 3d space? (Godot Q&A)
- How to rotate the camera around an object? [3D] (Godot Q&A)
The general thing I am seeing is that is is easiest to just have a node and use Godot's built in transform system handle it for you. So, if you have a mesh instance you want to rotate around a point, a scene tree like this is what you might want:
- root (has script)
- point
- MeshInstance
And then you can move the point around using $point.global_transform.origin = Vector3(1, 1, 1)
or similar and then use the normal Spatial functions for rotating, like #point.rotate_y(PI * delta)
for example.
Thanks!
Ok so i need helps with this.
Still cant find where you can rotate camera around object like you can in blender.
The code below does simple thing:
If mouse3 button
is pressed - sets is_rotating = true
and while true run rotate_camera(
) function
This dont work..
extends Node3D
@onready var camera_3d: Camera3D = $Camera3D
@onready var mouse_status: Label = $CanvasLayer/Control/PanelContainer/VBoxContainer/HBoxContainer/MouseStatus
@onready var mesh_instance_3d: MeshInstance3D = $MeshInstance3D
var is_rotating = false
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
#var lol = InputMap.get_actions()
if event.is_action_pressed("action_mouse_middle"):
# Rotate
mouse_status.text = "Rotate"
is_rotating = true
if event.is_action_released("action_mouse_middle"):
# Rotate
mouse_status.text = "None"
is_rotating = false
pass
if event.is_action_pressed("action_mouse_left"):
# Rotate
mouse_status.text = "Left"
if event.is_action_released("action_mouse_left"):
mouse_status.text = "None"
pass
if event is InputEventMouseMotion:
if is_rotating:
rotate_camera(event)
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
func rotate_camera(event:InputEventMouseMotion):
camera_3d.rotate_y(deg_to_rad(-event.relative.x * 0.2))
camera_3d.rotate_x(deg_to_rad(-event.relative.y * 0.2))
camera_3d.rotation.x = clampf(camera_3d.rotation.x, deg_to_rad(-90), deg_to_rad(90))
camera_3d.rotate_y(event.relative.y * 0.0010)
camera_3d.rotate_x(event.relative.x * 0.0010)
pass
I know how to do the rotation if you put camera inside 2 nodes:
func _input(event):
if not is_multiplayer_authority(): return
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
$h.rotate_y(deg_to_rad(-event.relative.x * h_sensitivity))
$h/v.rotate_x(deg_to_rad(-event.relative.y * h_sensitivity))
$h/v.rotation.x = clampf($h/v.rotation.x, deg_to_rad(cam_v_min), deg_to_rad(cam_v_max))
But i want to be able to do the same with just the camera.. im sure its possible? If not then ill just use the player char setup to do this ...
- Edited
kuligs2 Possible? Sure. Sensible? Not really. After all, that's exactly what the spring arm is for.
But if you really want to do it on your own: How's your trigonometry (the math stuff with sine and cosine)? You need to know your current angle of rotation around your center point and your new angle after the rotation, your distance from the center, calculate your new camera position and then change the x/y position of the camera accordingly. After that rotate the camera so that it faces the center point.
BTW, what are you trying to achieve? I feel like you are overcomplicating things.
kuligs2 I want to solve this problem without additional nodes.
"scientists were so preoccupied with whether they could, they didn't stop and ask themselves if they should've"
Can't you look into Godots source code and translate it to gdscript?
kuligs2
This is trivial, not sure why it's causing so much confusion.
Construct the rotation matrix and transform object's relative (to rotation origin) position by it. In the case of camera orbiting, the matrix you want is probably composed of delta rotations around up and local right axes. For camera, you'd also want to aim it at the rotation origin after each rotation.
extends Camera3D
@onready var target = $"../target"
const SENSITIVITY = .02
func orbit_point(origin: Vector3, point: Vector3, orbit_angle: Vector2) -> Vector3:
var d = point - origin
var t = Transform3D().rotated(Vector3.UP, orbit_angle.x).rotated(-d.cross(Vector3.UP).normalized(), orbit_angle.y)
return origin + t * d
func _input(e):
if e is InputEventMouseMotion:
global_position = orbit_point(target.global_position, global_position, e.relative*SENSITIVITY)
look_at(target.global_position)
xyz Thank you, dear Sir!. Will try to understand what happens, the oiler physics is too much for my brain.. also using transforms also not intuitive for me, not yet. Need to practice more to have a better understanding..
One thing to note, to make it feel like blender, you need to pass inverted event.relative value
func _input(e):
if e is InputEventMouseMotion:
global_position = orbit_point(target.global_position, global_position, -e.relative*SENSITIVITY) # < ---- Minus sign
look_at(target.global_position)
Here is a demo.
i guess ill sweat a bit over this
- Edited
extends Camera3D
@onready var target = $"../target"
const SENSITIVITY = .02
func orbit_transform(origin: Vector3, t: Transform3D, orbit_angle: Vector2) -> Transform3D:
var dt = Transform3D().rotated(t.basis.x, orbit_angle.y).rotated(Vector3.UP, orbit_angle.x)
t.basis = dt.basis * t.basis;
t.origin = origin + t.basis.z * (t.origin - origin).length()
return t
func _input(e):
if e is InputEventMouseMotion:
global_transform = orbit_transform(target.global_position, global_transform, e.relative*SENSITIVITY)
xyz is the king of the matrix and transforms