目标:我的场景中有一个SCNCylinder
对象。我希望能够拖动圆柱体的一端并向任意方向旋转圆柱体,同时将另一端保持在同一位置。
当前,我正在调用localRotate(by: SCNQuaternion)
首先旋转节点,然后计算移动圆柱体所需的位置偏移,以便另一端可以返回其原始位置。
如何一步一步实现目标,而不是现在正在做什么?
答案 0 :(得分:2)
您正在寻找pivot
属性。或者,由于当您使用SIMD类型的simdPivot
属性时,现代SceneKit通常可以更好地工作/使Swift变得更好/可以更轻松地与ARKit进行互操作。
请在文档中注意以下内容:
更改枢轴变换会以许多有用的方式更改这些行为。您可以:
- 相对于其位置偏移节点的内容。例如,通过将枢轴设置为平移变换,可以相对于球在地板上放置的位置而不是相对于其中心的位置,将包含球几何的节点定位。
- 移动节点的旋转轴。例如,通过平移变换,可以使节点绕远点旋转而不是围绕其中心旋转;而通过旋转变换,可以使旋转轴倾斜。
类似地,对于圆柱体,您可以使其圆柱体成为变换矩阵,该变换矩阵将原点平移其高度的一半,从而在一端而不是在中心给出“锚点”(用于位置和旋转更改)。像这样(未经测试):
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))
}
}
更一般而言,每当您使用基于场景图/基于变换层次结构的图形框架时,只要发现自己根据一种变换(旋转,平移等)影响另一种变换而进行数学运算,检查始终是一件好事可以为您完成数学运算的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