ARkit如何旋转一个物体以面对另一个物体
ARkit how to rotate an object to face another object
在开发 AR 游戏应用程序时,我 运行 遇到了一个(实际上是两个,但如果我想出解决这个问题的方法,那么还有另一个预期的问题)问题是我的 3D 对象不面对一个目标对象。第二个预期问题是这些物体是否有可能一直注视着其他移动的物体?
假设对于第一个问题,Xcode AR 的默认项目带有 spaceship 节点,它在 space 中浮动,当我添加一个object called like B,那么我想让spaceship的船头随时指向B对象。
第二个问题,如何监控ARSCNView
中所有运动物体的位置,并通过跟踪运动物体的运动使节点面向运动物体?就像 As 正在移动,B 一直在跟踪 As 的位置,并在应用程序中始终将自己指向 As。
你能给我一些提示或解决方案来解决这个问题吗?
(1)。您可以使用 billboardConstraint 始终使用其自由轴将焦点对准相机视图,例如
let billboardConstraint = SCNBillboardConstraint()
billboardConstraint.freeAxes = SCNBillboardAxis.Y
someNode.constraints = [billboardConstraint]
这个 someNode 总是聚焦在相机上,因为我们让 Y 轴可以自由旋转,而其他 2 轴相对于相机是固定的。
(2)。如何实现:2个节点将相互关注:
对于这种情况,我们可以使用 SCNLookAtConstraint。
赞:
let lookAtConstraints = SCNLookAtConstraint(target: node3)
node2.constraints = [lookAtConstraints]
所以 node2 在整个会话期间始终查看 node3。
为了理解,可以参考下面一段代码:
// Create different geometry nodes
enum GeometryType {
case Box
case Pyramid
case Capsule
case Cone
case Cylinder
}
func getGeometry(type: GeometryType) -> SCNGeometry {
switch type {
case .Box: return SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0.05)
case .Pyramid: return SCNPyramid(width: 0.2, height: 0.2, length: 0.2)
case .Capsule: return SCNCapsule(capRadius: 0.2, height: 0.1)
case .Cone: return SCNCone(topRadius: 0.0, bottomRadius: 0.2, height: 0.4)
case .Cylinder: return SCNCylinder(radius: 0.05, height: 0.2)
}
}
// Let's do the experiment:
func threeNodesExperiment() {
// always focus on camera view
let geometry1 : SCNGeometry! = getGeometry(type: .Pyramid)
geometry1.firstMaterial?.diffuse.contents = UIColor.red
let node1 = SCNNode(geometry: geometry1)
node1.position = SCNVector3Make(0.4, 0, -0.5)
let billboardConstraint = SCNBillboardConstraint()
billboardConstraint.freeAxes = SCNBillboardAxis.Y
node1.constraints = [billboardConstraint]
rootNode.addChildNode(node1)
// two nodes focusing each other
let geometry2 = getGeometry(type: .Cylinder)
geometry2.firstMaterial?.diffuse.contents = UIColor.green
let node2 = SCNNode(geometry: geometry2)
node2.position = SCNVector3Make(-0.1, 0, -0.5)
let geometry3 = getGeometry(type: .Box)
geometry3.firstMaterial?.diffuse.contents = UIColor.blue
let node3 = SCNNode(geometry: geometry3)
node3.position = SCNVector3Make(0.2, 0, -0.5)
let lookAtConstraints = SCNLookAtConstraint(target: node3)
node2.constraints = [lookAtConstraints]
[node2, node3].forEach{ rootNode.addChildNode([=12=]) }
}
输出:
node1(红色节点)始终聚焦于相机视图。 (改变相机位置并做实验)。
node2(绿色节点)和node3(蓝色节点)一直在看着对方。
对 3-D 节点使用一些 theta 值的自定义旋转:
(1)。使用 CAAnimation:
// (1). CAAnimation
private func rotateNode(node : SCNNode, theta : Double, with animation : Bool = false) {
if animation {
let rotation = CABasicAnimation(keyPath: "rotation")
rotation.fromValue = SCNVector4Make(0,1,0,0) // along x-z plane
rotation.toValue = SCNVector4Make(0,1,0,Float(theta))
rotation.duration = 3.0
rotation.repeatCount = Float.infinity
node.addAnimation(rotation, forKey: "Rotate it")
}
node.rotation = SCNVector4Make(0, 1, 0, Float(theta)) // along x-z plane
print("rotating node with angel :\(theta)")
}
(2)。 SCN事务
// (2). SCNTransaction
private func rotateUsingTransaction(node : SCNNode, theta : Double) {
SCNTransaction.begin()
SCNTransaction.animationDuration = 5.0
node.rotation = SCNVector4Make(0, 1, 0, Float(theta))
SCNTransaction.completionBlock = {
print("Transaction completed")
}
SCNTransaction.commit()
}
(3)。 SCNAction
// (3). SCNAction
private func moveUpDown(node : SCNNode) {
let moveUp = SCNAction.moveBy(x: 0, y: 1, z: 0, duration: 1)
moveUp.timingMode = .easeInEaseOut
let moveDown = SCNAction.moveBy(x: 0, y: -1, z: 0, duration: 1)
moveDown.timingMode = .easeInEaseOut
let moveSequence = SCNAction.sequence([moveUp,moveDown])
let moveLoop = SCNAction.repeatForever(moveSequence)
node.runAction(moveLoop)
}
在开发 AR 游戏应用程序时,我 运行 遇到了一个(实际上是两个,但如果我想出解决这个问题的方法,那么还有另一个预期的问题)问题是我的 3D 对象不面对一个目标对象。第二个预期问题是这些物体是否有可能一直注视着其他移动的物体?
假设对于第一个问题,Xcode AR 的默认项目带有 spaceship 节点,它在 space 中浮动,当我添加一个object called like B,那么我想让spaceship的船头随时指向B对象。
第二个问题,如何监控ARSCNView
中所有运动物体的位置,并通过跟踪运动物体的运动使节点面向运动物体?就像 As 正在移动,B 一直在跟踪 As 的位置,并在应用程序中始终将自己指向 As。
你能给我一些提示或解决方案来解决这个问题吗?
(1)。您可以使用 billboardConstraint 始终使用其自由轴将焦点对准相机视图,例如
let billboardConstraint = SCNBillboardConstraint()
billboardConstraint.freeAxes = SCNBillboardAxis.Y
someNode.constraints = [billboardConstraint]
这个 someNode 总是聚焦在相机上,因为我们让 Y 轴可以自由旋转,而其他 2 轴相对于相机是固定的。
(2)。如何实现:2个节点将相互关注: 对于这种情况,我们可以使用 SCNLookAtConstraint。
赞:
let lookAtConstraints = SCNLookAtConstraint(target: node3)
node2.constraints = [lookAtConstraints]
所以 node2 在整个会话期间始终查看 node3。
为了理解,可以参考下面一段代码:
// Create different geometry nodes
enum GeometryType {
case Box
case Pyramid
case Capsule
case Cone
case Cylinder
}
func getGeometry(type: GeometryType) -> SCNGeometry {
switch type {
case .Box: return SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0.05)
case .Pyramid: return SCNPyramid(width: 0.2, height: 0.2, length: 0.2)
case .Capsule: return SCNCapsule(capRadius: 0.2, height: 0.1)
case .Cone: return SCNCone(topRadius: 0.0, bottomRadius: 0.2, height: 0.4)
case .Cylinder: return SCNCylinder(radius: 0.05, height: 0.2)
}
}
// Let's do the experiment:
func threeNodesExperiment() {
// always focus on camera view
let geometry1 : SCNGeometry! = getGeometry(type: .Pyramid)
geometry1.firstMaterial?.diffuse.contents = UIColor.red
let node1 = SCNNode(geometry: geometry1)
node1.position = SCNVector3Make(0.4, 0, -0.5)
let billboardConstraint = SCNBillboardConstraint()
billboardConstraint.freeAxes = SCNBillboardAxis.Y
node1.constraints = [billboardConstraint]
rootNode.addChildNode(node1)
// two nodes focusing each other
let geometry2 = getGeometry(type: .Cylinder)
geometry2.firstMaterial?.diffuse.contents = UIColor.green
let node2 = SCNNode(geometry: geometry2)
node2.position = SCNVector3Make(-0.1, 0, -0.5)
let geometry3 = getGeometry(type: .Box)
geometry3.firstMaterial?.diffuse.contents = UIColor.blue
let node3 = SCNNode(geometry: geometry3)
node3.position = SCNVector3Make(0.2, 0, -0.5)
let lookAtConstraints = SCNLookAtConstraint(target: node3)
node2.constraints = [lookAtConstraints]
[node2, node3].forEach{ rootNode.addChildNode([=12=]) }
}
输出:
node1(红色节点)始终聚焦于相机视图。 (改变相机位置并做实验)。
node2(绿色节点)和node3(蓝色节点)一直在看着对方。
对 3-D 节点使用一些 theta 值的自定义旋转:
(1)。使用 CAAnimation:
// (1). CAAnimation
private func rotateNode(node : SCNNode, theta : Double, with animation : Bool = false) {
if animation {
let rotation = CABasicAnimation(keyPath: "rotation")
rotation.fromValue = SCNVector4Make(0,1,0,0) // along x-z plane
rotation.toValue = SCNVector4Make(0,1,0,Float(theta))
rotation.duration = 3.0
rotation.repeatCount = Float.infinity
node.addAnimation(rotation, forKey: "Rotate it")
}
node.rotation = SCNVector4Make(0, 1, 0, Float(theta)) // along x-z plane
print("rotating node with angel :\(theta)")
}
(2)。 SCN事务
// (2). SCNTransaction
private func rotateUsingTransaction(node : SCNNode, theta : Double) {
SCNTransaction.begin()
SCNTransaction.animationDuration = 5.0
node.rotation = SCNVector4Make(0, 1, 0, Float(theta))
SCNTransaction.completionBlock = {
print("Transaction completed")
}
SCNTransaction.commit()
}
(3)。 SCNAction
// (3). SCNAction
private func moveUpDown(node : SCNNode) {
let moveUp = SCNAction.moveBy(x: 0, y: 1, z: 0, duration: 1)
moveUp.timingMode = .easeInEaseOut
let moveDown = SCNAction.moveBy(x: 0, y: -1, z: 0, duration: 1)
moveDown.timingMode = .easeInEaseOut
let moveSequence = SCNAction.sequence([moveUp,moveDown])
let moveLoop = SCNAction.repeatForever(moveSequence)
node.runAction(moveLoop)
}