对象方向的平滑插值以跟踪相机
Smooth interpolation of object orientation to track the camera
我有一个 SCNNode 表示玩家在第一人称游戏(使用 ARKit)中持有的物品。
我将节点设为相机的子节点,以便它始终在观察者面前漂浮一小段距离。但是这个简单的设置使项目非常静态,只是粘在屏幕上。
更现实地说,如果我在我面前拿着一个物体,然后转向另一个方向,我的手的动作会稍微落后于我的脑袋。如果我把头向上或向下倾斜,我对物体的视角也会发生轻微的变化。
我如何在 SceneKit 中模拟它?
This question 有一些关于延迟追逐节点的相机的想法,并且可能会反向工作。对于倾斜,也许我必须考虑加速度计,但要对其进行约束,以免物体旋转太多。
我没有将项目设为相机的子节点,而是将项目设为名为 arms
的新不可见节点的子节点。 arms
节点不是 camera 的子节点,但我使用 SCNTransformConstraint
来约束它的转换,如下所示:
// ~~ Not the final code ~~ Do not use ~~
// Set up the viewer's "arms" to follow the camera using a dampened constraint
arms = SCNNode()
let armconstraint = SCNTransformConstraint.init(inWorldSpace: false) {
(node: SCNNode, _) -> SCNMatrix4 in
// Bind the arm's transformation to the camera's
return self.sceneView.pointOfView!.convertTransform(SCNMatrix4Identity, to: node)
}
armconstraint.influenceFactor = 0.5
arms!.constraints = [ armconstraint ]
sceneView.scene.rootNode.addChildNode(arms!)
使用低 influenceFactor
的想法,这样 arms
就不会僵硬地保持在镜头前,而是稍微延迟一下。
效果一般;它可能会明显生涩。所以我试着把它分成两个单独的约束:一个 SCNDistanceConstraint
保持相机和 arms
之间的距离为 0,一个 SCNTransformConstraint
同步 arms
方向但是不是它的位置。
我发现虽然 距离 约束是完美的,但在方向上使用分数 influenceFactor
会导致 arms
发狂,旋转隔着屏幕疯狂!如果它是 1.0
则 arms
节点严格跟随相机但没有故障。
原来,在SCNConstraint.influenceFactor
的文档中,它说:
This property has no effect on SCNTransformConstraint
objects.
嗯,我想知道为什么——节点的 transform
、position
和 orientation
是可动画的,所以看起来它们可以顺利插值,没有问题。
原来有一种叫做Slerp的技术,它是一种在四元数之间进行插值的方法。因此,每次调用 SCNTransformConstraint
时,我都可以在 arms
的当前位置和相机的位置之间进行插值,而不是使用 influenceFactor
。这是可以接受的平滑度。
我有一个 SCNNode 表示玩家在第一人称游戏(使用 ARKit)中持有的物品。
我将节点设为相机的子节点,以便它始终在观察者面前漂浮一小段距离。但是这个简单的设置使项目非常静态,只是粘在屏幕上。
更现实地说,如果我在我面前拿着一个物体,然后转向另一个方向,我的手的动作会稍微落后于我的脑袋。如果我把头向上或向下倾斜,我对物体的视角也会发生轻微的变化。
我如何在 SceneKit 中模拟它?
This question 有一些关于延迟追逐节点的相机的想法,并且可能会反向工作。对于倾斜,也许我必须考虑加速度计,但要对其进行约束,以免物体旋转太多。
我没有将项目设为相机的子节点,而是将项目设为名为 arms
的新不可见节点的子节点。 arms
节点不是 camera 的子节点,但我使用 SCNTransformConstraint
来约束它的转换,如下所示:
// ~~ Not the final code ~~ Do not use ~~
// Set up the viewer's "arms" to follow the camera using a dampened constraint
arms = SCNNode()
let armconstraint = SCNTransformConstraint.init(inWorldSpace: false) {
(node: SCNNode, _) -> SCNMatrix4 in
// Bind the arm's transformation to the camera's
return self.sceneView.pointOfView!.convertTransform(SCNMatrix4Identity, to: node)
}
armconstraint.influenceFactor = 0.5
arms!.constraints = [ armconstraint ]
sceneView.scene.rootNode.addChildNode(arms!)
使用低 influenceFactor
的想法,这样 arms
就不会僵硬地保持在镜头前,而是稍微延迟一下。
效果一般;它可能会明显生涩。所以我试着把它分成两个单独的约束:一个 SCNDistanceConstraint
保持相机和 arms
之间的距离为 0,一个 SCNTransformConstraint
同步 arms
方向但是不是它的位置。
我发现虽然 距离 约束是完美的,但在方向上使用分数 influenceFactor
会导致 arms
发狂,旋转隔着屏幕疯狂!如果它是 1.0
则 arms
节点严格跟随相机但没有故障。
原来,在SCNConstraint.influenceFactor
的文档中,它说:
This property has no effect on
SCNTransformConstraint
objects.
嗯,我想知道为什么——节点的 transform
、position
和 orientation
是可动画的,所以看起来它们可以顺利插值,没有问题。
原来有一种叫做Slerp的技术,它是一种在四元数之间进行插值的方法。因此,每次调用 SCNTransformConstraint
时,我都可以在 arms
的当前位置和相机的位置之间进行插值,而不是使用 influenceFactor
。这是可以接受的平滑度。