defold-orthographic icon indicating copy to clipboard operation
defold-orthographic copied to clipboard

screen_to_world and FarZ

Open zendorx opened this issue 10 months ago • 6 comments

Hello! I have question, but probably it is some kind of issue. I set FarZ = 1000, set projection to FIXED_ZOOM and rotated camera (-30, 0, 0)

Since I want to place all GO in 3d space I want to raycast to it. But I noticed that function screen_to_world returns different coordinates for mouse position if change FarZ (nothing else changed)

Снимок экрана 2024-04-15 в 15 28 44

I think that if camera stay on one place and ortographic size is same then world coordinates of mouse should remain same

zendorx avatar Apr 15 '24 13:04 zendorx

Update, if FarZ + NearZ == 0 than world position is right in space of camera object. But if NearZ -1 and FarZ 5000 than it returns coordinate far from camera for 2500 points

zendorx avatar Apr 15 '24 14:04 zendorx

I haven't looked into this very closely but it is likely that the screen to world calculation is not correct when the camera is rotated on the x or y axis.

britzl avatar Apr 18 '24 08:04 britzl

Здравствуйте! У меня вопрос, но, вероятно, это какая-то проблема. Я установил FarZ = 1000, установил проекцию на FIXED_ZOOM и повернул камеру (-30, 0, 0)

Поскольку я хочу разместить все GO в трехмерном пространстве, я хочу выполнить на него радиопередачу. Но я заметил, что функция screen_to_world возвращает другие координаты для положения мыши, если изменить FarZ (больше ничего не изменилось)

Снимок экрана 2024-04-15 в 15 28 44 Я думаю, что если камера остается на одном месте и ортографический размер такой же, то мировые координаты мыши должны оставаться неизменными

You fix it?

KorolevSoftware avatar Jul 30 '24 14:07 KorolevSoftware

I have this problem

KorolevSoftware avatar Jul 30 '24 14:07 KorolevSoftware

local function calculate_view_new(camera, camera_world_pos, camera_world_rotation, offset)
	local rot = camera_world_rotation
	local pos = camera_world_pos - vmath.rotate(rot, OFFSET)
	if offset then
		pos = pos + offset
	end

	local look_at = pos + vmath.rotate(rot, VECTOR3_MINUS1_Z)
	local up = vmath.rotate(rot, VECTOR3_UP)
	local view = vmath.matrix4_look_at(pos, look_at, up)
	return view
end

function M.screen_to_world_ray(camera_id, screen, plane_normal, point_on_plane)

	screen.x = screen.x * DISPLAY_WIDTH / WINDOW_WIDTH
	screen.y = screen.y * DISPLAY_HEIGHT / WINDOW_HEIGHT

	local camera = cameras[camera_id]
	local camera_world_position = go.get_world_position(camera.id)
	local camera_world_rotation = go.get_world_rotation(camera.id)
	
	-- Phasa 1 camera local
	local projection = camera.projection
	local idle_view =  calculate_view_new(camera, camera_world_position, vmath.quat())

	-- Base
	local viewport = camera.viewport or VECTOR4
	local viewport_width = viewport.z * DISPLAY_WIDTH / WINDOW_WIDTH
	local viewport_height = viewport.w * DISPLAY_HEIGHT / WINDOW_HEIGHT
	local viewport_left = viewport.x * DISPLAY_WIDTH / WINDOW_WIDTH
	local viewport_bottom = viewport.y * DISPLAY_HEIGHT / WINDOW_HEIGHT

	local s = vmath.vector3(screen)
	s.x = (s.x - viewport_left) * (DISPLAY_WIDTH / viewport_width)
	s.y = (s.y - viewport_bottom) * (DISPLAY_HEIGHT / viewport_height)
	
	local camera_local_position = M.unproject(idle_view, projection, s)
	camera_local_position.z =  camera_world_position.z
	
	-- Phasa 2 rotation 
	local from_rotation = camera_local_position - camera_world_position
	from_rotation = vmath.rotate(camera_world_rotation, from_rotation)
	from_rotation = from_rotation + camera_world_position

	local direction = vmath.rotate(camera_world_rotation, vmath.vector3(0,0, -1))

	-- Phase 3 projection to plane
	local denom = vmath.dot(plane_normal, direction)
	if denom == 0 then
		-- ray is perpendicular to plane normal, so there are either 0 or infinite intersections
		return
	end
	local t = vmath.dot(point_on_plane - from_rotation, plane_normal)/denom
	print(from_rotation+ t*direction)
	return from_rotation+ t*direction
end
function on_input(self, action_id, action)
	local word_pos = camera.screen_to_world_ray(hash("/camera"), vmath.vector3(action.screen_x, action.screen_y, 0), vmath.vector3(0, 0, -1), vmath.vector3(0))
	action.x = word_pos.x
	action.y = word_pos.y
	msg.post("#cursor", "input", { action_id = action_id, action = action })
end

I make this and add to camera.lua. And this work great!

KorolevSoftware avatar Jul 31 '24 12:07 KorolevSoftware

fix to screen_x and screen_y

KorolevSoftware avatar Aug 05 '24 14:08 KorolevSoftware