簡體   English   中英

如何讓實體不斷查看 RealityKit 中的相機,類似於 SceneKit 中的 Billboard Constraint

[英]How can I get an entity to constantly look at the camera in RealityKit similar to Billboard Constraint from SceneKit

我有一個應用程序,我正在嘗試從 SceneKit 更新到 RealityKit,而我在 RealityKit 中難以復制的功能之一是讓實體不斷地看着相機。 在 SceneKit 中,這是通過向節點添加以下廣告牌約束來實現的:

let billboardConstraint = SCNBillboardConstraint()

billboardConstraint.freeAxes = [.X, .Y]
startLabelNode.constraints = [billboardConstraint]

這將允許 startLabelNode 自由旋轉,使其始終面向相機,而 startLabelNode 不會改變其 position。

但是,我似乎無法找到使用 RealityKit 執行此操作的方法。 我已經嘗試過“lookat”方法,它似乎無法提供不斷面對鏡頭的能力。 這是一個簡短的示例應用程序,我嘗試在 RealityKit 中實現它的一個版本,但它不提供讓實體像在 SceneKit 中那樣不斷面對相機的能力:

import UIKit
import RealityKit
import ARKit

class ViewController: UIViewController, ARSessionDelegate {
    @IBOutlet weak var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        arView.session.delegate = self
        arView.environment.sceneUnderstanding.options = []
        arView.debugOptions.insert(.showSceneUnderstanding) // Display a debug visualization of the mesh.
        arView.renderOptions = [.disablePersonOcclusion, .disableDepthOfField, .disableMotionBlur] // For performance, disable render options that are not required for this app.
        arView.automaticallyConfigureSession = false
        let configuration = ARWorldTrackingConfiguration()
        if ARWorldTrackingConfiguration.supportsSceneReconstruction(.mesh) {
            configuration.sceneReconstruction = .mesh
        } else {
            print("Mesh Classification not available on this device")
            configuration.worldAlignment = .gravity
            configuration.planeDetection = [.horizontal, .vertical]
        }
        configuration.environmentTexturing = .automatic
        arView.session.run(configuration)
        
        UIApplication.shared.isIdleTimerDisabled = true // Prevent the screen from being dimmed to avoid interrupting the AR experience.
    }

    @IBAction func buttonPressed(_ sender: Any) {
        let screenWidth = arView.bounds.width
        let screenHeight = arView.bounds.height
        let centerOfScreen = CGPoint(x: (screenWidth / 2), y: (screenHeight / 2))
        
        if let raycastResult = arView.raycast(from: centerOfScreen, allowing: .estimatedPlane, alignment: .any).first
        {
            addStartLabel(at: raycastResult.worldTransform)
        }
    }
    
    func addStartLabel(at result: simd_float4x4) {
        let resultAnchor = AnchorEntity(world: result)
        resultAnchor.addChild(clickToStartLabel())
        arView.scene.addAnchor(resultAnchor)
    }
    
    func clickToStartLabel() -> ModelEntity {
        let text = "Click to Start Here"
        let textMesh = MeshResource.generateText(text, extrusionDepth: 0.001, font: UIFont.boldSystemFont(ofSize: 0.01))
        let textMaterial = UnlitMaterial(color: .black)
        let textModelEntity = ModelEntity(mesh: textMesh, materials: [textMaterial])
        textModelEntity.generateCollisionShapes(recursive: true)
        textModelEntity.position.x -= textMesh.width / 2
        textModelEntity.position.y -= textMesh.height / 2
        
        let planeMesh = MeshResource.generatePlane(width: (textMesh.width + 0.01), height: (textMesh.height + 0.01))
        let planeMaterial = UnlitMaterial(color: .white)
        let planeModelEntity = ModelEntity(mesh: planeMesh, materials: [planeMaterial])
        planeModelEntity.generateCollisionShapes(recursive:true)
        // move the plane up to make it sit on the anchor instead of in the middle of the anchor
        planeModelEntity.position.y += planeMesh.height / 2
        planeModelEntity.addChild(textModelEntity)
        
        // This does not always keep the planeModelEntity facing the camera
        planeModelEntity.look(at: arView.cameraTransform.translation, from: planeModelEntity.position, relativeTo: nil)
                
        return planeModelEntity
    }
}

extension MeshResource {
    var width: Float
    {
        return (bounds.max.x - bounds.min.x)
    }

    var height: Float
    {
        return (bounds.max.y - bounds.min.y)
    }
}

查看 function 是讓缺失功能在 RealityKit 中工作的最佳方法,還是有更好的方法讓實體不斷面對相機?

k - 我對 RK 沒有太多了解,但假設實體是一個場景包節點? - 然后對其設置約束,它將被迫始終面對'targetNode'。 如果它以您想要的方式工作,那么您可能必須嘗試最初創建節點的方式,即它面向的方向。

func setTarget()
    {
        node.constraints = []
        let vConstraint = SCNLookAtConstraint(target: targetNode)
        vConstraint.isGimbalLockEnabled = true
        node.constraints = [vConstraint]
    }

我能夠找到我的問題的答案。 添加以下代碼塊允許實體不斷地看着相機:

func session(_ session: ARSession, didUpdate frame: ARFrame) {
    planeModelEntity.look(at: arView.cameraTransform.translation, from: planeModelEntity.position(relativeTo: nil), relativeTo: nil)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM