我正在尝试将 toTorque 应用于场景中的节点。文件说明:
扭矩矢量的每个分量涉及围绕包含物理主体的 SCNNode 对象的局部坐标系中的相应轴的旋转。例如,应用{0.0,0.0,1.0}的扭矩会导致节点绕其 z-axis 逆时针旋转。
但是在我的测试中,似乎物理动画不会影响对象的实际位置。因此,轴保持静止(即使实际节点明显移动)。这导致始终从相同方向(在启动场景时 z 轴的任何位置)施加扭矩。
我希望能够应用扭矩,使其相对于对象始终保持不变(e.g. 导致节点在节点的 presentationNode 的 z-axis 周围逆时针旋转而不是位置节点 had(has?)当场景启动时)
3 回答
SceneKit 使用每个节点的两个版本:模型节点定义静态行为,表示节点实际上涉及动态行为并在屏幕上使用。这个分区镜像了 Core Animation 中使用的分区,并启用了隐式动画等功能(你可以在其中执行诸如 set
node.position
之类的操作并让它为新值设置动画,而不需要代码的其他部分查询node.position
必须处理中间值动画)。物理在表示节点上运行,但在场景空间中的某些 cases--like 这个 one--takes 输入。
但是,表示节点和场景之间的唯一区别在于坐标空间,因此您需要做的就是将矢量从表示空间转换为场景空间。 (场景的根节点不应该通过物理,动作或飞行动画进行转换,因此 model-scene 空间和 presentation-scene space.)之间没有实际区别。为此,请使用 SceneKit 提供的坐标转换方法之一,例如convertPosition:fromNode: 。
这是一个 Swift 游乐场,展示了你的困境:
第二次旋转有效地旋转金字塔围绕屏幕 y-axis,而不是金字塔的 y-axis - 穿过金字塔顶点的金字塔。正如你所指出的那样,它在第一次轮换之前绕着金字塔的 y-axis 旋转; i.e。场景的 y-axis(不受物理影响),而不是表示节点(通过物理旋转)。
要修复它,请插入以下行(在以
var axis
开头的行之后):对convertPosition:fromNode:的调用说“给我一个场景坐标空间中的矢量,它等于 presentation-node 空间中的这个”。当您在转换轴周围应用扭矩时,它会有效地转换回演示节点的空间以模拟物理,因此您可以看到它围绕您想要的轴旋转。
更新:有一些坐标空格错误,但最终结果几乎相同。
不幸的是,rickster 提供的解决方案对我不起作用:(
试图解决这个难题,我创造了(我相信的)一个非常 sub-standard 解决方案(更多的概念证明)。它涉及在我想要找到的轴上创建(null)对象,然后我使用它们的位置来找到与轴对齐的向量。
因为我有一个相当复杂的场景,我从 COLLADA 文件加载它。在该文件中,我已经建模了一个简单的坐标三脚架:三个正交的圆柱体,顶部有锥体(可以更容易地看到正在发生的事情)。
然后我将这个三脚架物体约束到我试图施加扭矩的物体上。这样我就有了一些对象,它允许我在我试图施加扭矩的对象的 presentationNode 的轴上检索两个点。然后我可以使用这两个点来确定应用扭矩的矢量。
正如你可能看到的,我在 SceneKit 中相当缺乏经验,但即使我可以看到很多 easier/optimised 解决方案确实退出,但我无法找到它:(
我最近遇到了同样的问题,如何将扭矩从物体的局部空间转换为
applyTorque
方法所需的世界空间。使用节点的convertPosition:toNode
和fromNode
方法的问题在于它们也将节点的转换应用于转矩,因此这仅在节点为 0,0,0 时才有效。这些方法的作用是将 SCNVector3 视为具有 1.0 的 w 分量的 vec4。我们只想应用旋转,换句话说,我们希望 vec4 的 w 分量为 0.与 SceneKit 不同,GLKit 为我们希望 vec3s 乘以的方式提供了 2 个选项:GLKMatrix4MultiplyVector3在哪里
和GLKMatrix4MultiplyVector3WithTranslation在哪里
我们想要的是前者,只是轮换,而不是翻译。
所以,我们可以往返 GLKit。例如,将局部 x 轴(1,0,0)(例如俯仰旋转)转换为施加扭矩所需的全局轴,将如下所示:
然而,更多的 Swiftian 方法是为 mat4 * vec3 添加一个
*
运算符,它将 vec3 视为具有 0.0 w 组件的 vec4。像这样:虽然这个算子假设我们希望我们的 vec3s 如何成倍增加,但我的理由是,由于
convertPosition
方法已经将 w 视为 1,因此使用*
运算符也是多余的。您还可以添加一个 mat4 * SCNVector4 运算符,让用户明确选择他们是否希望 w 为 0 或 1。
因此,我们可以写下:而不是从 SceneKit 往返到 GLKit。
您可以使用此方法通过一次
applyTorque
调用在多个轴上应用旋转。所以说如果你有棒输入你希望棒上的 x 是偏航(局部 yUp-axis)和棒上的 y 是俯仰(局部 x-axis),但是 flight-sim 样式“向下拉回/向上”,那么你可以设置为SCNVector3(input.y, -input.x, 0)