2017-06-28 44 views
0

我正在測試ARKit的實現,我的一部分實驗只是導入動畫模型並讓它跟隨Apple場景中其他靜態模型的AR場景運動項目。動畫3D模型遵循ARKit場景的錯誤運動

我從Apple的SceneKit示例中抓取了一個動畫3D模型 https://developer.apple.com/library/content/samplecode/SceneKitAnimations/Introduction/Intro.html 並將其放入簡單的ARKit測試項目中。 https://viewar.com/apple-augmented-reality-arkit-for-ios/

結果是:它顯示了模型,同時也是動畫模型,但模型始終「跟隨」我而不是在AR空間中保持相同的位置。 奇怪的是,它不僅僅是粘在屏幕上的同一個位置上,而是在AR空間中保持在頭頂上方。

我對新事物太陌生,不知道發生了什麼。 你們有什麼想法嗎?

代碼是這樣的。

class ViewController: UIViewController, ARSCNViewDelegate { 

    @IBOutlet var sceneView: ARSCNView! 

    var _animations = [CAAnimation]() 
    var charNode : SCNNode! 

    override func viewDidLoad() { 
     super.viewDidLoad()   
     // Set the view's delegate 
     sceneView.delegate = self   
     // Show statistics such as fps and timing information 
     sceneView.showsStatistics = true   
     // Create a new scene (Keep this ship just as a reference) 
     let scene = SCNScene(named: "art.scnassets/ship.scn")!   
     // Set the scene to the view 
     sceneView.scene = scene   
     // Load the DAE file and the associated animations 
     loadSceneAndAnimations();   
     // Be idle by default 
     playAnimation(ASCAnimation.Walk); 
    } 

    // MARK: Playing animations 
    func playAnimation(_ animation: ASCAnimation) { 
     // Use the same animation key for all the animations except "idle". 
     // When we will add an animation it will replace the animation currently 
     // playing (if any) but the idle animation will remain active for ever. 
     let key:String = animation == .Idle ? "idleAnimation" : "otherAnimation"; 

     // Add the animation - it will start playing right away 
     sceneView.scene.rootNode.addAnimation(_animations[animation.rawValue], forKey: key); 
    } 

    // MARK: Animation loading  
    func loadSceneAndAnimations() {   
     // Load the character from one of our dae documents, for instance "idle.dae" 
     let idleURL = Bundle.main.url(forResource: "art.scnassets/idle", withExtension: "dae"); 
     let idleScene = try! SCNScene(url: idleURL!, options: nil); 

     // Merge the loaded scene into our main scene in order to 
     // place the character in our own scene 
     for child in idleScene.rootNode.childNodes { 
      sceneView.scene.rootNode.addChildNode(child) 
     } 

     // Load all the animations from their respective dae document 
     // The animation identifier can be found in the Node Properties inspector of the Scene Kit editor integrated into Xcode 
     loadAnimation(animation: .Attack, sceneName: "art.scnassets/attack", animationIdentifier: "attackID"); 
     loadAnimation(animation: .Die, sceneName: "art.scnassets/die", animationIdentifier: "DeathID"); 
     loadAnimation(animation: .Idle, sceneName: "art.scnassets/idle", animationIdentifier: "idleAnimationID"); 
     loadAnimation(animation: .Run, sceneName: "art.scnassets/run", animationIdentifier: "RunID"); 
     loadAnimation(animation: .Walk, sceneName: "art.scnassets/walk", animationIdentifier: "WalkID"); 
    } 

    func loadAnimation(animation:ASCAnimation, sceneName:String, animationIdentifier:String) { 
     let sceneURL = Bundle.main.url(forResource: sceneName, withExtension: "dae"); 
     let sceneSource = SCNSceneSource(url: sceneURL!, options: nil); 
     let animationObject = sceneSource?.entryWithIdentifier(animationIdentifier, withClass: CAAnimation.self) 

     // Store the animation for later use 
     _animations.append(animationObject!); 

     // Whether or not the animation should loop 
     if animation == .Idle || animation == .Run || animation == .Walk { 
      animationObject?.repeatCount = MAXFLOAT; 
     } 
    } 

    override func viewWillAppear(_ animated: Bool) { 
     super.viewWillAppear(animated)   
     // Create a session configuration 
     let configuration = ARWorldTrackingSessionConfiguration()   
     // Run the view's session 
     sceneView.session.run(configuration) 
    } 

    override func viewWillDisappear(_ animated: Bool) { 
     super.viewWillDisappear(animated)   
     // Pause the view's session 
     sceneView.session.pause() 
    } 

    func session(_ session: ARSession, didFailWithError error: Error) { 
     // Present an error message to the user 
    }  
    func sessionWasInterrupted(_ session: ARSession) { 
     // Inform the user that the session has been interrupted, for example, by presenting an overlay   
    }  
    func sessionInterruptionEnded(_ session: ARSession) { 
     // Reset tracking and/or remove existing anchors if consistent tracking is required   
    } 
} 

回答

0

看一看的ARSceneViewDelegate,有一個方法

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor)

當ARKit檢測表面它增加了一個節點到現場,你可以把你的3D模型。您還需要適當的設置會話:

let configuration = ARWorldTrackingSessionConfiguration() 
configuration.planeDetection = .horizontal 

欲瞭解更多信息,看看蘋果公司提供的ARKit示例代碼: https://github.com/gao0122/ARKit-Example-by-Apple/tree/master/ARKitExample

+0

感謝您的評論,但與動畫模型有什麼關係?我的問題是在AR空間中的定位與靜態3D模型正確發生,但與具有動畫的3D模型無關 –

0

我自己解決它。 它太愚蠢了,但它只是因爲模型呈現非常巨大的尺寸,就像數百米的巨人。由於它太大,我在幾米左右的移動根本沒有任何影響。不好的是它也漂浮得很高,所以它看起來體型適中。通過給出約1/100的比例變換,它變得正常。