简体   繁体   English

VR 中的 SceneKit 相机移动

[英]SceneKit camera movement in VR

I have created VR version to my application with the help of this https://github.com/stevenjs/VR-iOS-Experiment我在这个https://github.com/stevenjs/VR-iOS-Experiment的帮助下为我的应用程序创建了 VR 版本

Now I want move my cameraNode when I start moving along with my phone.现在,当我开始带着手机移动时,我想移动我的 cameraNode。 I'm trying to use userAcceleration from core motion, But I have no clue to how to do this.我正在尝试从核心运动中使用 userAcceleration,但我不知道如何执行此操作。 Also I'm new to core motion.我也是核心运动的新手。

Please help me to solve this.请帮我解决这个问题。

This code will adapt to your device orientation ... it is basically a sphereNode with a cameraNode in the middle.此代码将适应您的设备方向……它基本上是一个中间有一个 cameraNode 的 sphereNode。 Core Motion controls the camera view. Core Motion 控制相机视图。

import UIKit
import SceneKit
import CoreMotion
import SpriteKit
import AVFoundation

class Video360VC: UIViewController {

    @IBOutlet weak var sceneView: SCNView!

    let motionManager = CMMotionManager()
    let cameraNode = SCNNode()
    var player: AVPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        startSelected()
    }

    func startNewPlayer(fileURL: URL, fileURLSub: URL){
        player = AVPlayer(url: fileURL)
        let videoNode = SKVideoNode(avPlayer: player!)
        let size = CGSize(width: 4096, height: 2048)

        videoNode.size = size
        videoNode.position = CGPoint(x: size.width/2, y: size.height/2)

        let spriteScene = SKScene(size: size)
        spriteScene.scaleMode = .resizeFill
        spriteScene.addChild(videoNode)

        let sphereNode = createSphereNode(material:spriteScene)
        configureScene(node: sphereNode)
        guard motionManager.isDeviceMotionAvailable else {
            fatalError("Device motion is not available")
        }

        startCameraTracking()
        player?.isMuted = true
        player?.play()
    }


    func createSphereNode(material: AnyObject?) -> SCNNode {
        let sphere = SCNSphere(radius: 20.0)
        sphere.firstMaterial!.isDoubleSided = true
        sphere.firstMaterial!.diffuse.contents = material
        let sphereNode = SCNNode(geometry: sphere)
        sphereNode.position = SCNVector3Make(0,0,0)
        sphereNode.rotation = SCNVector4Make(1, 0, 0, Float.pi)
        return sphereNode
    }

    func configureScene(node sphereNode: SCNNode) {
        // Set the scene
        let scene = SCNScene()
        sceneView.scene = scene

        //test mode help
        sceneView.showsStatistics = false
        sceneView.allowsCameraControl = false

        // Camera, ...
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3Make(0, 0, 0)
        scene.rootNode.addChildNode(sphereNode)
        scene.rootNode.addChildNode(cameraNode)
    }

    func startCameraTracking() {
        motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
        motionManager.startDeviceMotionUpdates(to: OperationQueue.main) {
            [weak self](data: CMDeviceMotion?, error: Error?) in
            guard let data = data else { return }

            self?.cameraNode.camera?.fieldOfView = 90
            self?.cameraNode.orientation = data.gaze(atOrientation: .landscapeRight)
        }
    }
}

extension CMDeviceMotion {

    func gaze(atOrientation orientation: UIInterfaceOrientation) -> SCNVector4 {

        let attitude = self.attitude.quaternion
        let aq = GLKQuaternionMake(Float(attitude.x), Float(attitude.y), Float(attitude.z), Float(attitude.w))

        let final: SCNVector4

        switch orientation {

        case .landscapeRight:

            let cq = GLKQuaternionMakeWithAngleAndAxis(Float(Float.pi/2), 0, 1, 0)
            let q = GLKQuaternionMultiply(cq, aq)

            final = SCNVector4(x: -q.y, y: q.x, z: q.z, w: q.w)

        case .landscapeLeft:

            let cq = GLKQuaternionMakeWithAngleAndAxis(Float(-Float.pi), 0, 1, 0)
            let q = GLKQuaternionMultiply(cq, aq)

            final = SCNVector4(x: q.y, y: -q.x, z: q.z, w: q.w)

        case .portraitUpsideDown:

            let cq = GLKQuaternionMakeWithAngleAndAxis(Float(Float.pi), 1, 0, 0)
            let q = GLKQuaternionMultiply(cq, aq)

            final = SCNVector4(x: -q.x, y: -q.y, z: q.z, w: q.w)

        case .unknown:

            fallthrough

        case .portrait:

            let cq = GLKQuaternionMakeWithAngleAndAxis(Float(-Float.pi), 1, 0, 0)
            let q = GLKQuaternionMultiply(cq, aq)

            final = SCNVector4(x: q.x, y: q.y, z: q.z, w: q.w)

        default:
            print("Default")
        }

        return final
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM