ARkit如何旋转对象以面对另一个对象

问题描述 投票:3回答:1

在开发一个AR游戏应用程序时,我碰到了一个(实际上是两个,但如果我找到解决这个问题的方法,那么还有另一个预期的问题)问题就是我的3D对象没有面对目标对象。第二个预期问题是对象是否可能继续查看其他移动对象?

让我们说,对于第一个问题,AR的Xcode默认项目带有在空间中浮动的太空船节点,当我添加一个名为B的对象时,我希望太空船的头部指向B对象随时。

对于第二个问题,如何监视ARSCNView中移动物体的所有位置,并通过跟踪它们的运动使节点面向移动物体?就像As正在移动而B正在跟踪As的位置并指出自己在应用程序中的整个时间。

你能给我一些提示或解决方案来解决这个问题吗?

ios swift augmented-reality arkit
1个回答
3
投票

(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。

For understanding, you can refer the following piece of code:

 // 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(蓝色节点)总是互相看。

Custom Rotation with some theta value to a 3-D node:

(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)
 }
© www.soinside.com 2019 - 2024. All rights reserved.