You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何获取ARSCNView内CGPoint对应的世界坐标

解决点击点转世界坐标的问题

嘿,我懂你现在的困境——已经把帧中心点转世界坐标的逻辑跑通了,但没法偏移到实际点击的屏幕位置,对吧?其实核心问题就是原函数里硬编码了屏幕中心的UV坐标,咱们只要把这部分改成动态传入的点击位置对应的UV就行,下面一步步来调整你的代码:

核心思路拆解

原函数之所以只能处理中心点,是因为它用了固定的(0.5, 0.5)作为屏幕UV(也就是屏幕中心的归一化坐标)。要支持任意点击点,咱们需要:

  • 让函数接收具体的屏幕点击坐标(比如screenX和screenY)
  • 将屏幕坐标转换成归一化UV坐标(范围0到1,再转成NDC空间的[-1,1])
  • 把原函数里的中心UV替换成这个计算出来的点击UV
  • 保留原有的视图/投影矩阵逆运算逻辑(这部分是从屏幕空间转世界空间的核心)

修改后的完整代码示例

假设你的原函数是基于3D引擎的通用逻辑,下面是调整后的getScreenCoordinates函数(保留了你原有的注释风格,只修改关键部分):

def getScreenCoordinates(screen_x, screen_y, screen_width, screen_height, view_matrix, projection_matrix):
    """
    将屏幕点击坐标转换为世界空间的方向向量和位置向量
    参数:
        screen_x: 点击点的屏幕X坐标(比如鼠标X)
        screen_y: 点击点的屏幕Y坐标(比如鼠标Y)
        screen_width: 屏幕宽度
        screen_height: 屏幕高度
        view_matrix: 相机的视图矩阵
        projection_matrix: 相机的投影矩阵
    返回:
        tuple: (世界空间方向向量, 世界空间位置向量)
    """
    # 步骤1:将屏幕坐标转换为NDC空间坐标(范围[-1,1])
    # 注意:不同引擎屏幕原点位置不同!比如Unity是左下角(0,0),Unreal是左上角(0,0)
    # 如果是左上角原点,反转Y轴:ndc_y = 1.0 - (screen_y / screen_height) * 2.0 + 1.0?不对,正确公式是下面的注释版
    ndc_x = (screen_x / screen_width) * 2.0 - 1.0
    ndc_y = (screen_y / screen_height) * 2.0 - 1.0  # 左下角原点用这个
    # ndc_y = (1.0 - (screen_y / screen_height)) * 2.0 - 1.0  # 左上角原点用这个

    # 构建NDC空间的齐次点(z=-1对应近平面,保证是相机前方的点)
    ndc_point = (ndc_x, ndc_y, -1.0, 1.0)

    # 步骤2:计算视图投影矩阵的逆矩阵(原函数已有逻辑,直接复用)
    view_projection_matrix = multiply_matrices(projection_matrix, view_matrix)
    inv_view_projection_matrix = inverse_matrix(view_projection_matrix)

    # 步骤3:将NDC点转换为世界空间点
    world_point = multiply_matrix_point(inv_view_projection_matrix, ndc_point)
    # 齐次坐标转笛卡尔坐标:必须除以w分量
    world_point = (world_point[0]/world_point[3], world_point[1]/world_point[3], world_point[2]/world_point[3])

    # 步骤4:计算世界空间方向向量(从相机位置指向世界点)
    camera_world_pos = get_camera_world_position(view_matrix)  # 原函数已有获取相机位置的逻辑
    world_direction = normalize_vector((
        world_point[0]-camera_world_pos[0],
        world_point[1]-camera_world_pos[1],
        world_point[2]-camera_world_pos[2]
    ))

    # 返回方向向量和位置向量
    return (world_direction, world_point)

关键注意点

  • 屏幕坐标系差异:一定要根据你用的引擎调整Y轴计算!比如Unreal的屏幕原点在左上角,就必须用注释里的反转Y轴公式,否则转换出来的Y坐标会上下颠倒。
  • 矩阵运算顺序:不同引擎的矩阵乘法顺序可能不同(比如是投影乘视图,还是视图乘投影),如果转换结果不对,先检查这里的顺序是否和原函数一致。
  • 齐次除法:转换后的世界点必须除以w分量,否则坐标会出现缩放失真的问题,这是3D坐标转换的关键步骤。

调用示例

在点击事件里,你可以这样调用函数获取点击点的世界坐标:

# 获取鼠标点击的屏幕坐标
mouse_x, mouse_y = get_mouse_position()
# 获取屏幕尺寸
screen_w, screen_h = get_screen_size()
# 获取相机的视图和投影矩阵
camera_view = get_camera_view_matrix()
camera_proj = get_camera_projection_matrix()

# 转换为世界坐标
world_dir, world_pos = getScreenCoordinates(mouse_x, mouse_y, screen_w, screen_h, camera_view, camera_proj)

# 现在world_pos就是点击点对应的世界空间位置啦!

这样修改后,你的函数就不再局限于帧中心点,而是可以处理任意屏幕点击位置的转换了。如果还有细节不对,比如矩阵运算的语法,你可以根据自己用的语言/引擎微调~

内容的提问来源于stack exchange,提问作者Anthony Krivonos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:09:18