ARKit случайное вращение в позиции - PullRequest
0 голосов
/ 30 октября 2018

У меня проблемы с ротацией ARKit. Я создаю узел My3DPlayer:SCNNode, который содержит videoNode:SKVideoNode. Проблема, которую я испытываю, заключается в том, что она делает случайные вращения (броски). Он не создает никаких проблем с подачей и поворотом, однако он будет поворачиваться в случайном направлении, каждый раз, когда я открываю приложение. Я бы хотел, чтобы ориентация была прямо над якорем, который я использую. У меня правильный размер, который мне нравится, но я немного запутался в повороте.

import UIKit
import ARKit
import AVKit

class My3DPlayer: SCNNode {

    var player:AVPlayer!

    init(geometry: SCNGeometry?) {
        super.init()
        self.geometry = geometry
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    convenience init(anchor: ARImageAnchor, currentFrame:ARFrame) {
        self.init(geometry: nil)
        self.createPlayer(anchor, currentFrame)
    }

    //Returns a 3d Player of a set size
    private func createPlayer(_ anchor:ARImageAnchor, _ frame:ARFrame) {

        let physicalSize = anchor.referenceImage.physicalSize
        print("Init Player W/ physicalSize: \(physicalSize)")

        //Create video
        let path = Bundle.main.path(forResource: "Bear", ofType: "mov")
        let asset = AVAsset(url: URL(fileURLWithPath: path!))
        let track = asset.tracks(withMediaType: AVMediaType.video).first!
        let playerItem = AVPlayerItem(asset: asset)
        self.player = AVPlayer(playerItem: playerItem)
        var videoSize = track.naturalSize.applying(track.preferredTransform)
        videoSize = CGSize(width: abs(videoSize.width), height: abs(videoSize.height))
        print("Init Video W/ size: \(videoSize)")

        //Do something when video ended
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying(note:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)

        //Add observer to determine when Player is ready
        player.addObserver(self, forKeyPath: "status", options: [], context: nil)

        //Create video Node
        let videoNode = SKVideoNode(avPlayer: player)

         //Create 2d scene to put 2d player on - SKScene
        let scene = SKScene(size: videoSize)
        videoNode.position = CGPoint(x: videoSize.width/2, y: videoSize.height/2)
        videoNode.size = scene.size

        //To adjust to landscape and portrait weird af
        videoNode.zRotation = CGFloat(-Double.pi)*90/180
        print(videoNode.zRotation * 180/CGFloat(Double.pi))
        let width = videoNode.size.width
        videoNode.size.width = videoNode.size.height
        videoNode.size.height = width

        //Add videoNode to scene
        scene.addChild(videoNode)

        //Get ratio difference from physicalsize and video size
        let widthRatio = Float(physicalSize.width)/Float(videoSize.width)
        let heightRatio = Float(physicalSize.height)/Float(videoSize.height)
        let finalRatio = [widthRatio, heightRatio].min()!

        //Create a Plane (SCNPlane) to put the SKScene on
        let plane = SCNPlane(width: videoSize.width, height: videoSize.height)
        plane.firstMaterial?.diffuse.contents = scene
        plane.firstMaterial?.isDoubleSided = true

        //Set Self.geometry = plane
        self.geometry = plane

        //Show Node
        self.transform = SCNMatrix4(anchor.transform)
        let appearanceAction = SCNAction.scale(to: CGFloat(finalRatio), duration: 0.4)
        appearanceAction.timingMode = .easeOut

        //Set initial scale to 0 then use action to scale up
        self.scale = SCNVector3Make(0, 0, 0)
        self.runAction(appearanceAction)

        //This rotates it to lay down
        self.eulerAngles = SCNVector3(Double.pi*90/180, 0, 0)
    }
}

Вот как я ссылаюсь на изображение (мне нужно удалить реальное изображение, которое я использую для создания изображения AR, поскольку оно является моей привязанностью. Это был самый удобный и легко доступный объект для игры).

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else {
        return
    }

    guard let currentFrame = self.sceneView.session.currentFrame else {
        return
    }

    DispatchQueue.main.async {
        self.videoPlayer3D = My3DPlayer(anchor: imageAnchor, currentFrame: currentFrame)
        self.sceneView.scene.rootNode.addChildNode(self.videoPlayer3D)
    }
}

Вот несколько примеров, однако, иногда они полностью горизонтальны по сравнению с вертикальными. Это кажется случайным.

one rotation here

another rotation here

...