ARKit:在室外放置多个物体时将虚拟物体固定在相机框架上

时间:2018-07-20 09:58:53

标签: ios swift arkit

使用ARKit将对象放置在平面上时,当对象总数超过一个时,有时对象会固定在相机框架上,并且实际上并未在真实场景中渲染。我猜想这可能是由于某些外部因素造成的,例如照明,feature points,真实世界飞机的质量等。是否有人遇到过这种情况,或者是否知道解决此问题的方法或解决方法?防止这种情况?谢谢!

编辑:这是一些处理对象渲染的代码:

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    DispatchQueue.main.async {
        self.virtualObjectInteraction.updateObjectToCurrentTrackingPosition()
        self.updateFocusSquare()
    }

    if objectsViewController != nil {
        let planeAnchor = focusSquare.currentPlaneAnchor
        objectsViewController?.updateObjectAvailability(for: planeAnchor)
    }

    // If the object selection menu is open, update availability of items
    if objectsViewController != nil {
        let planeAnchor = focusSquare.currentPlaneAnchor
        objectsViewController?.updateObjectAvailability(for: planeAnchor)
    }

    // If light estimation is enabled, update the intensity of the directional lights
    if let lightEstimate = session.currentFrame?.lightEstimate {
        sceneView.updateDirectionalLighting(intensity: lightEstimate.ambientIntensity, queue: updateQueue)
    } else {
        sceneView.updateDirectionalLighting(intensity: 1000, queue: updateQueue)
    }
}

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
    updateQueue.async {
        for object in self.virtualObjectLoader.loadedObjects {
            object.adjustOntoPlaneAnchor(planeAnchor, using: node)
        }
    }
}

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    updateQueue.async {
        if let planeAnchor = anchor as? ARPlaneAnchor {
            for object in self.virtualObjectLoader.loadedObjects {
                object.adjustOntoPlaneAnchor(planeAnchor, using: node)
            }
        } else {
            if let objectAtAnchor = self.virtualObjectLoader.loadedObjects.first(where: { $0.anchor == anchor }) {
                objectAtAnchor.simdPosition = anchor.transform.translation
                objectAtAnchor.anchor = anchor
            }
        }
    }
}

func setTransform(_ newTransform: float4x4,
                  relativeTo cameraTransform: float4x4,
                  smoothMovement: Bool,
                  alignment: ARPlaneAnchor.Alignment,
                  allowAnimation: Bool) {
    let cameraWorldPosition = cameraTransform.translation
    var positionOffsetFromCamera = newTransform.translation - cameraWorldPosition

    if simd_length(positionOffsetFromCamera) > 10 {
        positionOffsetFromCamera = simd_normalize(positionOffsetFromCamera)
        positionOffsetFromCamera *= 10
    }

    if smoothMovement {
        let hitTestResultDistance = simd_length(positionOffsetFromCamera)

        // Add the latest position and keep up to 10 recent distances to smooth with.
        recentVirtualObjectDistances.append(hitTestResultDistance)
        recentVirtualObjectDistances = Array(recentVirtualObjectDistances.suffix(10))

        let averageDistance = recentVirtualObjectDistances.average!
        let averagedDistancePosition = simd_normalize(positionOffsetFromCamera) * averageDistance
        simdPosition = cameraWorldPosition + averagedDistancePosition
    } else {
        simdPosition = cameraWorldPosition + positionOffsetFromCamera
    }

    updateAlignment(to: alignment, transform: newTransform, allowAnimation: allowAnimation)
}

func placeVirtualObject(_ virtualObject: VirtualObject) {
    guard let cameraTransform = session.currentFrame?.camera.transform,
        let focusSquareAlignment = focusSquare.recentFocusSquareAlignments.last,
        focusSquare.state != .initializing else {
        return
    }

    let focusSquareScaleInverse = 1.0 / focusSquare.simdScale.x
    let scaleMatrix = float4x4(uniformScale: focusSquareScaleInverse)
    let focusSquareTransformWithoutScale = focusSquare.simdWorldTransform * scaleMatrix

    virtualObjectInteraction.selectedObject = virtualObject
    virtualObject.setTransform(focusSquareTransformWithoutScale,
                               relativeTo: cameraTransform,
                               smoothMovement: false,
                               alignment: focusSquareAlignment,
                               allowAnimation: false)

    updateQueue.async {
        self.sceneView.scene.rootNode.addChildNode(virtualObject)
        self.sceneView.addOrUpdateAnchor(for: virtualObject)
    }
}

0 个答案:

没有答案