在 SceneKit 中围绕锚点旋转

AJ *_* Z. 1 3d graphics ios scenekit arkit

目标SCNCylinder我的场景中有一个物体。我希望能够拖动圆柱体的一端并向任何方向旋转圆柱体,同时将另一端保持在同一位置。

目前,我正在调用localRotate(by: SCNQuaternion)首先旋转节点,然后计算移动圆柱体所需的位置偏移量,以便另一端可以回到其原始位置。

如何一步一步实现目标,而不是我现在正在做的事情?

ric*_*ter 5

pivot物业是你在找什么。或者,由于现代 SceneKit 通常工作得更好/使 Swift 更好/在您使用 SIMD 类型时与 ARKit 更容易互操作,simdPivot属性。

请注意文档中的这一点:

改变枢轴变换以许多有用的方式改变这些行为。你可以:

  • 相对于其位置偏移节点的内容。例如,通过将枢轴设置为平移变换,您可以相对于球体放置在地板上的位置而不是相对于其中心定位包含球体几何形状的节点。
  • 移动节点的旋转轴。例如,使用平移变换,您可以使节点围绕远处的点旋转,而不是围绕其中心旋转,使用旋转变换,您可以倾斜旋转轴。

类似地,对于圆柱体,您可以使其枢轴成为一个变换矩阵,将原点平移其高度的一半,在一端而不是在中心为其提供一个“锚点”(用于位置和旋转更改)。像这样的东西(未经测试):

let cylinder = SCNCylinder(radius: /*...*/, height: /*...*/)
let cylinderNode = SCNNode(geometry: cylinder)

cylinderNode.simdPivot = float4x4(translation: cylinder.height / 2)

extension float4x4 {
    init(translation vector: float3) {
        self.init(float4(1, 0, 0, 0),
                  float4(0, 1, 0, 0),
                  float4(0, 0, 1, 0),
                  float4(vector.x, vector.y, vector.z, 1))
    }
}
Run Code Online (Sandbox Code Playgroud)

更一般地说,每当您使用基于场景图/变换层次结构的图形框架时,任何时候您发现自己根据一个变换(旋转、平移等)进行数学运算以影响另一个变换,检查 API 总是好的可以为你做那个数学运算——因为做那种数学运算就是变换层次结构的全部内容。

如果没有一个 API 非常适合您的需求,请记住层次结构本身非常适合进行相关转换。例如,如果您希望一个节点围绕另一个节点沿圆形轨道运行,则无需使用正弦和余弦设置其位置……只需将其设为另一个节点的子节点,然后旋转另一个节点即可。

在这种情况下,pivot 相当于使用节点层次结构的便利。您也可以创建一个中间节点并在其中移动圆柱体(类似这样):

let cylinder = SCNCylinder(radius: /*...*/, height: /*...*/)
let cylinderNode = SCNNode(geometry: cylinder)

let offsetNode = SCNNode()
offsetNode.addChildNode(cylinderNode)
cylinderNode.simdPosition.y = cylinder.height / 2

offsetNode.position = /*...*/ // set world-space position of end of cylinder
offsetNode.eulerAngles.x = /*...*/ // rotate cylinder around its end
Run Code Online (Sandbox Code Playgroud)