From e90213a1cc022a76703b784ac32bef7d72e77345 Mon Sep 17 00:00:00 2001 From: Artsiom Trubchyk Date: Thu, 22 Jan 2026 10:25:11 +0300 Subject: [PATCH] Update world-to-screen example to use built-in camera API --- render/world_to_screen/example.md | 30 ++++++++++++++++++- render/world_to_screen/example/hud.gui_script | 1 + render/world_to_screen/example/player.script | 27 ++--------------- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/render/world_to_screen/example.md b/render/world_to_screen/example.md index af4c3dd6..96aeac5d 100644 --- a/render/world_to_screen/example.md +++ b/render/world_to_screen/example.md @@ -9,7 +9,35 @@ thumbnail: thumbnail.png This example shows how to convert world positions to screen coordinates for UI positioning. It features: -* A `world_to_screen()` function that transforms 3D world positions to 2D screen coordinates using the camera's view and projection matrices. +* Use of the built-in `camera.world_to_screen()` API to transform 3D world positions to 2D screen coordinates. +* A reference Lua `world_to_screen()` implementation (below) kept as an example to help understand how the conversion works internally. * A ghost character that rotates around a crypt in 3D space while floating up and down. * A player name label in the GUI that follows the character's world position by converting it to screen coordinates. * Demonstrates practical use of world-to-screen conversion for positioning UI elements relative to 3D objects. + +Note: The reference Lua version does not preserve depth information and always returns `z = 0` to keep the code simpler. + +```lua +--- Converts a world position to screen coordinates. +-- This function transforms a 3D world position to 2D screen coordinates using the camera's +-- view and projection matrices. The resulting coordinates are in screen space where (0,0) +-- is the bottom-left corner of the screen. +-- +-- @param world_position vector3 The world position to convert. +-- @param camera_url url|string The camera component URL to use for the transformation. +-- @return number screen_x The X coordinate in screen space. +-- @return number screen_y The Y coordinate in screen space. +-- @return number screen_z Always returns 0 (depth information is not preserved). +local function world_to_screen(world_position, camera_url) + local proj = camera.get_projection(camera_url) + local view = camera.get_view(camera_url) + + local view_proj = proj * view + local scr_coord = view_proj * vmath.vector4(world_position.x, world_position.y, world_position.z, 1) + local w, h = window.get_size() + scr_coord.x = (scr_coord.x / scr_coord.w + 1) * 0.5 * w + scr_coord.y = (scr_coord.y / scr_coord.w + 1) * 0.5 * h + + return vmath.vector3(scr_coord.x, scr_coord.y, 0) +end +``` diff --git a/render/world_to_screen/example/hud.gui_script b/render/world_to_screen/example/hud.gui_script index 116cafc1..045f9e10 100644 --- a/render/world_to_screen/example/hud.gui_script +++ b/render/world_to_screen/example/hud.gui_script @@ -12,6 +12,7 @@ function on_message(self, message_id, message, sender) if message_id == hash("update_data") then local screen_position = message.screen_position -- Use screen position to set the position of the player name node + screen_position.z = 0 -- "z" should be reset to 0. gui.set_screen_position(self.name_node, screen_position) end end diff --git a/render/world_to_screen/example/player.script b/render/world_to_screen/example/player.script index e3821661..a3446d1b 100644 --- a/render/world_to_screen/example/player.script +++ b/render/world_to_screen/example/player.script @@ -1,30 +1,7 @@ -go.property("camera_url", msg.url("/camera#camera")) +go.property("camera_url", msg.url("/camera#camera")) -- URL of the camera component go.property("hud_url", msg.url("/ui#hud")) go.property("angle", -45) -- we use this property to animate the rotation of the player around the center of the scene ---- Converts a world position to screen coordinates. --- This function transforms a 3D world position to 2D screen coordinates using the camera's --- view and projection matrices. The resulting coordinates are in screen space where (0,0) --- is the bottom-left corner of the screen. --- --- @param world_position vector3 The world position to convert. --- @param camera_url url|string The camera component URL to use for the transformation. --- @return number screen_x The X coordinate in screen space. --- @return number screen_y The Y coordinate in screen space. --- @return number screen_z Always returns 0 (depth information is not preserved). -local function world_to_screen(world_position, camera_url) - local proj = camera.get_projection(camera_url) - local view = camera.get_view(camera_url) - - local view_proj = proj * view - local scr_coord = view_proj * vmath.vector4(world_position.x, world_position.y, world_position.z, 1) - local w, h = window.get_size() - scr_coord.x = (scr_coord.x / scr_coord.w + 1) * 0.5 * w - scr_coord.y = (scr_coord.y / scr_coord.w + 1) * 0.5 * h - - return vmath.vector3(scr_coord.x, scr_coord.y, 0) -end - function init(self) -- Get the IDs of the player view and UI objects self.player_view_id = go.get_id("player_view") @@ -54,7 +31,7 @@ function update(self, dt) -- Update the world transform of the player UI object and convert the world position to screen coordinates go.update_world_transform(self.player_ui_id) local world_pos = go.get_world_position(self.player_ui_id) - local screen_pos = world_to_screen(world_pos, self.camera_url) + local screen_pos = camera.world_to_screen(world_pos, self.camera_url) -- Send the screen position to the HUD script msg.post(self.hud_url, "update_data", { screen_position = screen_pos }) end