将 SceneKit 对象放置在 SCNCamera 当前方向的前面

2024-03-31

我想在用户点击屏幕时创建一个新的 SceneKit 节点,并让它以设定的距离直接出现在相机前面。为了测试,这将是一个 SCNText 读取“您点击此处”。它还应该与视线成直角,即“面向”相机。

所以,鉴于self.camera.orientationSCNVector4(或类似),我怎样才能:

  1. 生成将节点置于相机“前面”给定距离的 SCNVector3 吗?
  2. 生成 SCNVector4 (或 SCNQuaternion)来定向节点,使其“面向”相机?

我怀疑(2)的答案是它与“self.camera.orientation”相同?但是(1)让我有点迷失。

我看到很多类似的问题,比如this one https://stackoverflow.com/questions/39402064/scenekit-use-transform-or-directly-manipulate-rotation-position-properties-if-g,但没有答案。


您不需要这么多数学运算——SceneKit 实际上已经在做这些数学运算了,所以您只需要向它询问正确的结果即可。

[如何]生成 SCNVector3,将节点放置在相机“前面”给定的距离?

在托管相机的节点的局部坐标系中,“前”是 -Z 方向。如果你把东西放在(0, 0, -10)相对于相机,它直接位于相机视线的中心,距离 10 个单位。有两种方法可以做到这一点:

  1. 只需将文本节点设为相机的子节点即可。

    cameraNode.addChildNode(textNode)
    textNode.position = SCNVector3(x: 0, y: 0, z: -10)
    

    请注意,这也会使其移动with相机:如果相机改变方向或位置,textNode一起去兜风。 (想象一下反向的自拍杆——在一端旋转手机,另一端随之摆动。)

    由于文本节点位于相机节点空间中,因此您可能也不需要任何其他内容即可使其面向相机。 (默认方向SCNText相对于其父空间使文本面向相机。)

  2. (iOS 11 / macOS 10.13 / Xcode 9 / 等中的新增功能)SceneKit 现在包含一些方便的访问器和方法,可以用更少的步骤执行各种相对几何数学。这些属性和方法中的大多数都以新的形式提供,支持系统范围的 SIMD 库,而不是使用 SCN 向量/矩阵类型 - 并且 SIMD 库具有内置的重载运算符等很好的功能。将它们放在一起,这样的操作就变成了单行:

    textNode.simdPosition = camera.simdWorldFront * distance
    

    (simdWorldFront是一个长度为 1.0 的向量,因此您可以通过缩放来改变距离。)

  3. 如果您仍然支持 iOS 10 / macOS 10.12 / 等,您仍然可以使用节点层次结构进行坐标转换。文本节点可以是场景的子节点(场景的rootNode,实际上),但你可以找到与你想要的相机空间坐标相对应的场景坐标空间位置。你实际上并不需要一个函数,但这可能可以解决问题:

    func sceneSpacePosition(inFrontOf node: SCNNode, atDistance distance: Float) -> SCNVector3 {
        let localPosition = SCNVector3(x: 0, y: 0, z: CGFloat(-distance))
        let scenePosition = node.convertPosition(localPosition, to: nil) 
             // to: nil is automatically scene space
        return scenePosition
    }
    textNode.position = sceneSpacePosition(inFrontOf: camera, atDistance: 3)
    

    在这种情况下,文本节点最初是相对于相机定位的,但并不保持与其“连接”。如果移动相机,节点将保持在原来的位置。由于文本节点位于场景空间中,因此它的方向也未连接到相机。

[如何]生成 SCNVector4(或 SCNQuaternion)来定向节点,使其“面向”相机?

这部分您不需要做太多事情,也可以完全交给 SceneKit,具体取决于您使用的第一个问题的答案。

  1. 如果您执行了上面的 (1) - 使文本节点成为相机节点的子节点 - 使其面向相机是一步操作。正如我所指出的,随着SCNText作为您的测试几何体,该步骤已经完成。在其局部坐标空间中,SCNText是直立的,并且从默认相机方向可读(即,朝 -Z 方向看,+Y 向上,+X 向右)。

    如果您有一些其他几何体想要面向相机,则只需将其定向一次,但您必须计算出适当的方向。例如,一个SCNPyramid它的点在 +Y 方向,因此如果您希望该点面向相机(注意,它很锐利),您需要将其绕 X 轴旋转.pi/2。 (你可以这样做eulerAngles, rotation, orientation or pivot.)

    由于它是相机的子级,因此您对其进行的任何旋转都将相对于相机进行,因此如果相机移动,它将保持指向相机。

  2. 如果您执行了上述 (2),您could尝试从场景空间角度计算出面对相机需要什么旋转,并在节点或相机移动时应用该旋转。但有一个 API 可以为您做到这一点。实际上有两个API:SCNLookAtConstraint使任何节点“面向”任何其他节点(由受约束节点的 -Z 方向确定),并且SCNBillboardConstraint有点相同,但需要一些额外的考虑,假设您不仅要面对某个其他节点,而且要具体面对相机.

    它仅使用默认选项就可以很好地工作:

    textNode.constraints = [ SCNBillboardConstraint() ]
    

额外的警告

如果您正在使用sceneSpacePosition上面的函数,并且你的相机节点的方向是在渲染时设置的 - 也就是说,你不设置transform, eulerAngles, rotation, or orientation直接对其进行操作,而是使用约束、动作、动画或物理来移动/定向相机 - 还有一件事需要考虑。

SceneKit 实际上在任何给定时间都有两个正在运行的节点层次结构:“模型”树和“演示”树。模型树是直接设置的transform(等)确实如此。所有其他移动/定向节点的方法都使用表示树。因此,如果您想使用相机相对空间计算位置,则需要相机的呈现节点:

textNode.position = sceneSpacePosition(inFrontOf: camera.presentation, atDistance: 3)
                                                        ~~~~~~~~~~~~~

(为什么会这样?除此之外,这样你就可以拥有隐式动画:setposition在交易内部,它会从旧位置动画到新位置。在该动画期间,模型position是你设置的,并且呈现节点不断改变它的position.)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 SceneKit 对象放置在 SCNCamera 当前方向的前面 的相关文章

随机推荐

  • 桌面应用程序转换器

    我使用 Desktop Bridge 一段时间了 最 近我开始遇到问题 它停止构建软件包 我尝试将其安装在不同的虚拟机上 但遇到了相同的错误 PowerShell Error Record DesktopAppConverter error
  • 如何使 CATransform3dMakeRotation 以另一种方式旋转?并链在一起

    我第一次使用一些核心动画 在实现可以翻转的扑克牌的过程中 我决定使用CALayer显示内容 不确定我将如何获得两侧 但这是另一个问题 并且我需要能够翻转它 移动它等等 我在用着CATransaction取得了一些成功 在下面的代码片段中 卡
  • 以识别自定义 if 语句的方式解析纯文本

    我有以下字符串 string The man has NUM DOGS dogs 我通过以下函数运行它来解析它 function parse text string global num dogs string str replace NU
  • Visual Studio 2010 中的代码指标

    我想知道 Visual Studio 2010 中的代码指标有哪些可用选项 我知道可以在 IDE 中对代码运行手动指标 但是还有其他选项吗 我想做的是 我和我的团队正在运行 Team Foundation Server 2010 并且我们设
  • phpunit 测试类未找到错误,而类存在?

    这是我的目录结构 application modules admin models User php 这是我的用户模型类 class admin Model User User php 这是我的 UserTest 类 带有简单的 Asser
  • 计算直线与 x 轴之间的角度

    我目前正在为 Android 开发一个简单的 2D 游戏 我有一个位于屏幕中心的固定对象 我试图让该对象旋转并指向用户触摸的屏幕区域 我有代表屏幕中心的常量坐标 我可以获得用户点击的点的坐标 我正在使用此论坛中概述的公式 如何获得两点之间的
  • glsl 中的 mat3(mat4 矩阵)语句有何作用?

    我正在做每个片段照明 并且在校正法线向量时 我得到了以下代码 vec3 f normal mat3 MVI normal 其中 MVI 是 mat4 MVI transpose inverse ModelViewMatrix 那么返回之后是
  • 如何处理 Blackberry Storm 中的 ButtonField 和 BitmapField 点击(触摸)事件?

    我创建了一个 ButtonField 和一个 BitmapField 像 public class MyCanvas extends MainScreen implements FieldChangeListener HorizontalF
  • 如何在Table View定制过程中调用“willDisplayHeaderView”方法?

    我想调用这些方法 void tableView UITableView tableView willDisplayHeaderView UIView view forSection NSInteger section NS AVAILABL
  • 如何防止标签在移动屏幕 Chart.js 上重叠

    我正在使用这个例子jsfiddle https jsfiddle net Trekels fec0v5kj 但是当我使用小屏幕时标签开始像这样重叠 我可以做什么来预防它 我想让它完全响应 我尝试改变长度和其他长宽比等 但没有成功 var c
  • 缓存是个好主意吗?如果是的话,在哪里?

    我有一个 ASP NET 网站 每天有 10 25 000 名访问者 节假日前的峰值超过 60 000 人 由于它是一个内容网站 因此页面 访问量也很高 我有一些特定的页面 它们产生了大约 60 的流量 这些页面有点复杂 并且数据库较多 s
  • Xcode 4.2:如何从子项目导入 .h 文件

    我是 Xcode 子项目的新手 在我的 iPhone 应用程序项目中MyProject 我正在尝试将一些常见代码重构为一个名为的静态库项目MyLibrary 我创建后MyLibrary并移动代码 MyProject不再编译 错误在于MyPr
  • 在 openCV 中连接足够近的轮廓

    我有一组从图像中检测到的轮廓 斑点 问题在于 一些斑点在斑点检测和平滑过程中被分割 我尝试使用以下代码 Mat outlines Mat zeros m3 size CV 8UC3 findContours m3 contours CV R
  • 多匹配布尔提升

    我正在尝试执行以下操作 curl X POST localhost 9200 magento customer search pretty 1 d query bool must multi match query john fields
  • cygwin git下的KDiff3不会调用

    为了与互联网上发布的许多解决方案保持一致 我安装了 KDiff3 并进行了修改 gitconfig如下所示来使用它 尽管如此 当我跑步时git diff HEAD HEAD在存储库中进行测试 我得到了默认工具执行的差异 我在 Windows
  • NestJS 在非模块文件中注入模块服务

    我有一个用于视图渲染的函数文件 我想在这里使用 Nestjs 模块服务 我的渲染文件是这样的 export default parse render 因此 为了在这里使用模块服务 我尝试像这样注入 import Inject from ne
  • Django URL 模板匹配(除了模式之外的所有内容)

    我需要一个 django 正则表达式 它实际上适用于 url 路由器来执行以下操作 匹配路由中不包含 api 的所有内容 以下不起作用 因为 django 无法反转 r api 通常的方法是对路由声明进行排序 以便包罗万象的路由被 api路
  • 下载文件时强制显示“另存为”对话框

    下面的代码将文件保存到用户的磁盘上 function handleSaveImg event const image canvas toDataURL const saveImg document createElement a saveI
  • C# 中的内部与公共

    我想知道两者之间的区别public and internal可见性修饰符 我们什么时候应该使用internal在课堂上以及何时public 我对什么时候应该使用方法感到困惑public or internal 我读到了internal可以通
  • 将 SceneKit 对象放置在 SCNCamera 当前方向的前面

    我想在用户点击屏幕时创建一个新的 SceneKit 节点 并让它以设定的距离直接出现在相机前面 为了测试 这将是一个 SCNText 读取 您点击此处 它还应该与视线成直角 即 面向 相机 所以 鉴于self camera orientat