ARKit - Как отобразить канал с виртуальной SCNCamera, размещенной на SCNPlane? - PullRequest
1 голос
/ 08 мая 2019

Я поместил некоторые объекты в пространство AR, используя ARKit и SceneKit. Это хорошо работает. Теперь я хотел бы добавить дополнительную камеру (SCNCamera), которая находится в другом месте сцены, прикрепленной и расположенной с помощью общего SCNNode. Он ориентирован на отображение текущей сцены с другой (фиксированной) перспективы.

Теперь я хотел бы показать этот дополнительный канал SCNCamera на i.Ex. SCNPlane (как диффузный первый материал) - как экран телевизора. Конечно, я знаю, что он будет отображать только контент SceneKit, который остается в фокусе камеры, а не остальную часть изображения ARKit (что, конечно, возможно только основной камерой). Тогда подойдет простой цветной фон.

Я видел учебные пособия, в которых описывается, как воспроизводить видеофайл на виртуальном дисплее в ARSpace, но мне нужна трансляция с камеры в реальном времени из моей текущей сцены.

Я определил эти объекты:

let camera = SCNCamera()
let cameraNode = SCNNode()

Затем в viewDidLoad я делаю это:

camera.usesOrthographicProjection = true
camera.orthographicScale = 9
camera.zNear = 0
camera.zFar = 100
cameraNode.camera = camera
sceneView.scene.rootNode.addChildNode(cameraNode)

Затем я вызываю свою функцию настройки, чтобы разместить виртуальный дисплей рядом со всеми вещами AR, а также расположить cameraNode (указывая в направлении, где объекты остаются на сцене)

cameraNode.position = SCNVector3(initialStartPosition.x, initialStartPosition.y + 0.5, initialStartPosition.z)

let cameraPlane = SCNNode(geometry: SCNPlane(width: 0.5, height: 0.3))
cameraPlane.geometry?.firstMaterial?.diffuse.contents = cameraNode.camera
cameraPlane.position = SCNVector3(initialStartPosition.x - 1.0, initialStartPosition.y + 0.5, initialStartPosition.z)

sceneView.scene.rootNode.addChildNode(cameraPlane)

Все компилируется и загружается ... Дисплей отображается в заданной позиции, но остается полностью серым. Ничего не отображается вообще из SCNCamera, который я вставил в сцену. Все остальное на AR-сцене работает хорошо, я просто не получаю никакого сигнала с этой камеры.

Gray plane instead of camera feed

У кого-нибудь есть подход, чтобы этот сценарий работал?

Чтобы еще лучше визуализировать, я добавил еще несколько экранов для печати. ​​

Ниже показано изображение через SCNCamera в соответствии с входом ARGeo. Но он занимает весь экран, вместо того, чтобы показывать его содержимое на SCNPlane, как мне нужно.

View from the SCNCamera

На следующем экране «Печать» отображается текущий результат ARView, полученный с помощью опубликованного кода. Как видите, серая плоскость дисплея остается серой - она ​​ничего не показывает.

Current AR View

Последний экран печати - это фотомонтаж, показывающий ожидаемый результат, который я хотел бы получить.

Expected or Desired AR View

Как это могло быть реализовано? Я что-то упустил здесь?

Ответы [ 2 ]

1 голос
/ 11 мая 2019

После некоторых исследований и сна я пришел к следующему рабочему решению (включая некоторые необъяснимые препятствия):

В настоящее время дополнительный канал SCNCamera не связан с SCNMaterial на SCNPlane, так как это былопервоначальная идея, но я буду использовать дополнительный SCNView (на данный момент)

В определениях я добавляю другой вид, например, так:

let overlayView   = SCNView() // (also tested with ARSCNView(), no difference)
let camera        = SCNCamera()
let cameraNode    = SCNNode()

, затем в viewDidLoad я настраиваю материалвот так ...

camera.automaticallyAdjustsZRange = true
camera.usesOrthographicProjection = false
cameraNode.camera                 = camera
cameraNode.camera?.focalLength    = 50
sceneView.scene.rootNode.addChildNode(cameraNode) // add the node to the default scene

overlayView.scene                    = scene // the same scene as sceneView
overlayView.allowsCameraControl      = false
overlayView.isUserInteractionEnabled = false
overlayView.pointOfView              = cameraNode // this links the new SCNView to the created SCNCamera
self.view.addSubview(overlayView)    // don't forget to add as subview

// Size and place the view on the bottom
overlayView.frame  = CGRect(x: 0, y: 0, width: self.view.bounds.width * 0.8, height: self.view.bounds.height * 0.25)
overlayView.center = CGPoint(x: self.view.bounds.width * 0.5, y: self.view.bounds.height - 175)

затем, в какой-то другой функции, я помещаю узел, содержащий SCNCamera, в желаемое положение и угол.

// (exemplary)
cameraNode.position = initialStartPosition + SCNVector3(x: -0.5, y: 0.5, z: -(Float(shiftCurrentDistance * 2.0 - 2.0)))          
cameraNode.eulerAngles = SCNVector3(-15.0.degreesToRadians, -15.0.degreesToRadians, 0.0)

Результат - это видокна (новый SCNView) в нижней части экрана, отображая тот же контент SceneKit, что и в основном sceneView, видимый через перспективу SCNCamera плюс положение его узла, и это очень красиво.

Main AR view plus additional view from other perspective

В обычном проекте iOS / Swift / ARKit эта конструкция генерирует некоторые побочные эффекты, с которыми можно бороться.

1) В основном, новый SCNView показывает содержимое SceneKit с желаемой точки зрения, но фон всегда является фактической подачей физической камеры.Я не мог понять, как сделать фон статичным цветом, по-прежнему отображая все содержимое SceneKit.Изменение свойства background новой сцены влияет также на всю основную сцену, что на самом деле НЕ желательно.

2) Это может показаться странным, но как только следующий код становится включенным (что необходимо для его работы):

overlayView.scene = scene

скорость анимации всей сцены (обе) удваивается!(Почему?)

Я исправил это, добавив / изменив следующее свойство, которое восстанавливает поведение скорости анимации почти как нормальное (по умолчанию):

// add or change this in the scene setup
scene.physicsWorld.speed = 0.5

3) Если есть действиякак и SCNAction.playAudio в проекте, все эффекты больше не будут воспроизводиться - пока я этого не сделаю:

overlayView.scene = nil

Конечно, дополнительный SCNView перестает работать, но все остальное возвращается кэто нормально.

0 голосов
/ 09 мая 2019

Используйте этот код (в качестве отправной точки), чтобы узнать, как настроить виртуальную камеру.

Просто создайте проект ARKit по умолчанию в Xcode и скопируйте и вставьте мой код:

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.showsStatistics = true
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        sceneView.scene = scene

        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(0, 0, 1)
        cameraNode.camera?.focalLength = 70
        cameraNode.camera?.categoryBitMask = 1
        scene.rootNode.addChildNode(cameraNode)

        sceneView.pointOfView = cameraNode
        sceneView.allowsCameraControl = true
        sceneView.backgroundColor = UIColor.darkGray

        let plane = SCNNode(geometry: SCNPlane(width: 0.8, height: 0.45))
        plane.position = SCNVector3(0, 0, -1.5)

        // ASSIGN A VIDEO STREAM FROM SCENEKIT-RECORDER TO YOUR MATERIAL
        plane.geometry?.materials.first?.diffuse.contents = capturedVideoFromSceneKitRecorder
        scene.rootNode.addChildNode(plane)
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        sceneView.session.run(configuration)
    }
}

ОБНОВЛЕНО :

Вот приложение SceneKit Recorder , которое вы можете адаптировать к вашим потребностям (вам не нужно записывать видео на диск,просто используйте поток CVPixelBuffer и назначьте его в качестве текстуры для рассеянного материала.

enter image description here

Надеюсь, это поможет.

...