在 viewDidLoad 期间应用的 SceneKit 节点旋转无效

Posted

技术标签:

【中文标题】在 viewDidLoad 期间应用的 SceneKit 节点旋转无效【英文标题】:SceneKit node rotation applied during viewDidLoad has no effect 【发布时间】:2019-04-04 15:24:47 【问题描述】:

我有一个 SceneKit 场景,其中包含来自 .dae 文件(从 Blender 导出)的参考节点以及直接在场景编辑器中添加的各种相机和灯光。为了使参考节点在编辑器中以正确的方向显示,它应用了旋转 (-90, 0, 0)。这不会延续到应用内视图,因此我已经成功地在从 viewDidLoad() 调用的函数中应用了旋转。

自从今天重构以来,没有发生轮换。代码仍然尝试以相同的方式应用更正 - 这只是一个整理。

各种 hack 确实成功地旋转了节点:

将旋转应用为持续时间为零的SCNAction.rotateTo(),而不是node.eulerAngles = 安排稍后应用轮换 (​​Timer.scheduledTimer(...))

这两者都表明存在时间问题,即我没有达到的预重构。 SceneKit 节点旋转是否仅在节点至少被渲染一次时才生效?幕后肯定有一些优化,因为即使延迟分配到 node.eulerAngles 也只会在导致值发生变化时对呈现的内容产生影响。

编辑:

仔细比较之前和之后的代码版本,发现了一个看似不重要的顺序变化。在原始文件中,我添加了一些生成的节点(SCNNode 的子类,其平面使用SKScene 作为纹理) 旋转参考节点(有效)之前。重构后,该顺序已颠倒。节点是兄弟姐妹,而不是后代,所以我不明白为什么这很重要,除非 SKScene-as-texture 将事情放慢到足以避免一些优化?

【问题讨论】:

【参考方案1】:

生成示例游戏代码并在 viewDidLoad 中应用旋转适用于 repeatForever 和 rotateBy 调用,但示例代码实际上并没有做太多事情。不确定这能证明什么,因为渲染循环实际上是在它自己的线程中处理的。在没有看到代码或渲染循环中发生了多少情况的情况下,很有可能您的旋转命令并不总是被处理,因为它们没有被注入渲染队列线程中。

或者,将模型旋转到搅拌机中的所需位置,然后为 Scenekit 设置 Y-Up。我对 Blender 不是很好,所以我保存了一些关于如何在 Blender 中旋转、保存和导出的文档——如果你需要,我可以发布。然后使用此命令行处理 Y-Up 的模型。

/Applications/Xcode.app/Contents/Developer/usr/bin/scntool --convert fighter0.dae --format c3d --output out.dae --force-y-up --force-interleaved --look -for-pvrtc-image

不确定你有多长,但我与这个斗争了很长时间,发现如果我的搅拌机模型从一开始就设置为正确的旋转并且也能在 XCode 中正确预览,它对我来说效果更好。在某些时候,您可能正在做一些旋转或 SCNLookat,而我的模型总是关闭。可能有更简单的方法来纠正它们,但是当它可以从一开始就设置为您想要的状态时,为什么还要进行额外的数学运算。

希望对您有所帮助。

【讨论】:

里面有一些有用的提醒,谢谢。由于它没有直接解决 SceneKit 为什么选择不应用请求的旋转的问题,所以我倾向于将这个问题留待一段时间。

以上是关于在 viewDidLoad 期间应用的 SceneKit 节点旋转无效的主要内容,如果未能解决你的问题,请参考以下文章

体育赛事期间的 OpenCV 横幅匹配

在检查互联网连接期间 iOS 应用程序冻结

在 viewDidLoad 之后加载图像

SpriteKit 正确的资产大小

在等待主视图加载时显示 UIView?

在触摸期间停止 UIScrollView 滚动