在开发一个AR游戏应用程序时,我碰到了一个(实际上是两个,但如果我找到解决这个问题的方法,那么还有另一个预期的问题)问题就是我的3D对象没有面对目标对象。第二个预期问题是对象是否可能继续查看其他移动对象?
让我们说,对于第一个问题,AR的Xcode默认项目带有在空间中浮动的太空船节点,当我添加一个名为B的对象时,我希望太空船的头部指向B对象随时。
对于第二个问题,如何监视ARSCNView
中移动物体的所有位置,并通过跟踪它们的运动使节点面向移动物体?就像As正在移动而B正在跟踪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($0) }
}
node1(红色节点)始终聚焦到摄像机视图。 (更改相机位置并进行实验)。
node2(绿色节点)和node3(蓝色节点)总是互相看。
(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)。 SCNTransaction
// (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)
}