Instantiating objects as child without rotation

Godot Version

v4.2.1.stable.official [b09f793f5]

Question

When I click on an Area3D, I want to add a cube at the location where I clicked. But when the Area3D is rotated, the click location is moved along with the rotation.

How do I get the cubes to instantiate at the click location?

rotate_intersect_ray0120-1260-ezgif.com-video-to-gif-converter

extends Node3D

var cube = preload("res://cube.tscn")

func _process(delta: float) -> void:
	if Input.is_action_pressed("ui_left"):
		$Area3D.rotation.y += delta
	if Input.is_action_pressed("ui_right"):
		$Area3D.rotation.y -= delta

func _physics_process(delta: float) -> void:
	if Input.is_action_just_released("lclick"):
		var world_pos = get_world_intersect_pos()
		if world_pos == Vector3.ZERO:
			return
		var new_cube = cube.instantiate()
		new_cube.position = world_pos
		find_child("cubes").add_child(new_cube)

func get_world_intersect_pos() -> Vector3:
	var space_state = get_world_3d().direct_space_state
	var cam: Camera3D = $Camera3D
	var mousepos = get_viewport().get_mouse_position()
	var origin = cam.project_ray_origin(mousepos)
	var end = origin + cam.project_ray_normal(mousepos) * 100
	var query = PhysicsRayQueryParameters3D.create(origin, end)
	query.collide_with_areas = true
	var result = space_state.intersect_ray(query)
	if "position" in result:
		return result["position"]
	else:
		return Vector3.ZERO

When interacting by mouse with a 3D object I would rather suggest to use physics mouse picking instead of calculating all steps by hand.
An example of how to do that can be seen in the _mouse_input_event function in the GUI in 3D Demo.

But to answer your question, try something like:

		var new_cube = cube.instantiate()
		var cubes = find_child("cubes")
		var local_pos = cubes.global_transform.affine_inverse().xform(world_pos)
		new_cube.position = local_pos
		cubes.add_child(new_cube)

Since you add new_cube as a child to cubes, the position needs to be in local coordinates of cubes.

that works great, thanks. slight syntax difference on my version though

var local_pos = cubes.global_transform.affine_inverse() * world_pos