Добавьте второй Anchor-образ в существующий проект ARKit - PullRequest
0 голосов
/ 30 апреля 2020

Недавно я следовал учебнику (этот) о том, как использовать отслеживание изображений с ARKit для отображения информации рядом с изображением трекера. Все получилось так, как и ожидалось, и я вполне доволен результатом, поскольку он соответствует тому, что я хотел создать. После изучения учебника я расширил приложение с помощью (простого) пользовательского интерфейса.

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

Это действительно мое последнее средство, поэтому я надеюсь, что найдется кто-то, кто сможет направить меня в правильном направлении, что для меня будет очень много значить! Я добавил код из файла Viewcontroller + ARSCNViewDelegate ниже и загрузил Xcode-проект на Google Drive, если кто-то захочет взглянуть на проект.

Ссылка на Google Drive

import UIKit
import SceneKit
import ARKit

extension ViewController: ARSCNViewDelegate {

// MARK: - ARSCNViewDelegate

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

    // Delegate rendering tasks to our `updateQueue` thread to keep things thread-safe!
    updateQueue.async {
        let physicalWidth = imageAnchor.referenceImage.physicalSize.width
        let physicalHeight = imageAnchor.referenceImage.physicalSize.height

        // Create a plane geometry to visualize the initial position of the detected image
        let mainPlane = SCNPlane(width: physicalWidth, height: physicalHeight)

        // This bit is important. It helps us create occlusion so virtual things stay hidden behind the detected image
        mainPlane.firstMaterial?.colorBufferWriteMask = .alpha

        // Create a SceneKit root node with the plane geometry to attach to the scene graph
        // This node will hold the virtual UI in place
        let mainNode = SCNNode(geometry: mainPlane)
        mainNode.eulerAngles.x = -.pi / 2
        mainNode.renderingOrder = -1
        mainNode.opacity = 1

        // Add the plane visualization to the scene
        node.addChildNode(mainNode)

        // Perform a quick animation to visualize the plane on which the image was detected.
        // We want to let our users know that the app is responding to the tracked image.
        self.highlightDetection(on: mainNode, width: physicalWidth, height: physicalHeight, completionHandler: {

            // Introduce virtual content
            self.displayDetailView(on: mainNode, xOffset: physicalWidth)

            // Animate the WebView to the right
            self.displayWebView(on: mainNode, xOffset: physicalWidth)

        })
    }
}

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

}



// MARK: - SceneKit Helpers

func displayDetailView(on rootNode: SCNNode, xOffset: CGFloat) {
    let detailPlane = SCNPlane(width: xOffset, height: xOffset * 1.4)
    detailPlane.cornerRadius = 0.25

    let detailNode = SCNNode(geometry: detailPlane)
    detailNode.geometry?.firstMaterial?.diffuse.contents = SKScene(fileNamed: "DetailScene")

    // Due to the origin of the iOS coordinate system, SCNMaterial's content appears upside down, so flip the y-axis.
    detailNode.geometry?.firstMaterial?.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)
    detailNode.position.z -= 0.5
    detailNode.opacity = 0

    rootNode.addChildNode(detailNode)
    detailNode.runAction(.sequence([
        .wait(duration: 1.0),
        .fadeOpacity(to: 1.0, duration: 1.5),
        .moveBy(x: xOffset * -1.1, y: 0, z: -0.05, duration: 1.5),
        .moveBy(x: 0, y: 0, z: -0.05, duration: 0.2)
        ])
    )
}

func displayWebView(on rootNode: SCNNode, xOffset: CGFloat) {
    // Xcode yells at us about the deprecation of UIWebView in iOS 12.0, but there is currently
    // a bug that does not allow us to use a WKWebView as a texture for our webViewNode
    // Note that UIWebViews should only be instantiated on the main thread!
    DispatchQueue.main.async {
        let request = URLRequest(url: URL(string: "https://nl.wikipedia.org/wiki/Taylor_Swift")!)
        let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 400, height: 672))
        webView.loadRequest(request)

        let webViewPlane = SCNPlane(width: xOffset, height: xOffset * 1.4)
        webViewPlane.cornerRadius = 0.25

        let webViewNode = SCNNode(geometry: webViewPlane)

        // Set the web view as webViewPlane's primary texture
        webViewNode.geometry?.firstMaterial?.diffuse.contents = webView
        webViewNode.position.z -= 0.5
        webViewNode.opacity = 0

        rootNode.addChildNode(webViewNode)
        webViewNode.runAction(.sequence([
            .wait(duration: 3.0),
            .fadeOpacity(to: 1.0, duration: 1.5),
            .moveBy(x: xOffset * 1.1, y: 0, z: -0.05, duration: 1.5),
            .moveBy(x: 0, y: 0, z: -0.05, duration: 0.2)
            ])
        )
    }
}

func highlightDetection(on rootNode: SCNNode, width: CGFloat, height: CGFloat, completionHandler block: @escaping (() -> Void)) {
    let planeNode = SCNNode(geometry: SCNPlane(width: width, height: height))
    planeNode.geometry?.firstMaterial?.isDoubleSided = true
    planeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.white
    planeNode.position.z += 0.1
    planeNode.opacity = 0

    rootNode.addChildNode(planeNode)
    planeNode.runAction(self.imageHighlightAction) {
        block()
    }
}

var imageHighlightAction: SCNAction {
    return .sequence([
        .wait(duration: 0.25),
        .fadeOpacity(to: 0.85, duration: 0.25),
        .fadeOpacity(to: 0.15, duration: 0.25),
        .fadeOpacity(to: 0.85, duration: 0.25),
        .fadeOut(duration: 0.5),
        .removeFromParentNode()
        ])
}

}
...