如何放置一个始终看着相机的 RealityKit 实体?

问题描述 投票:0回答:1

对于 SCNNodes,我们有

SCNBillboardConstraint
,那么有什么方法可以将此约束应用于实体(当使用 RealityKit 而不是 SceneKit 时),以便实体在设备移动时始终面向相机?

swift scenekit augmented-reality arkit realitykit
1个回答
9
投票

iOS版本

使用 look(at:from:upVector:relativeTo:) 实例方法将实体从给定位置定位并定向到目标。

       func look(at target: SIMD3<Float>, 
             from position: SIMD3<Float>, 
                  upVector: SIMD3<Float> = SIMD3<Float>(0, 1, 0),         
relativeTo referenceEntity: Entity?)

在你的代码中它可能看起来像这样:

entity?.look(at: otherEntity!.position, 
           from: entity!.position, 
       upVector: [0, 1, 0], 
     relativeTo: nil)



visionOS版本

visionOS 版本有一个附加参数,称为

forward

@available(visionOS 1.0, *)
@available(macOS, unavailable)
@available(iOS, unavailable)
@MainActor public func look(at target: SIMD3<Float>, 
                            from position: SIMD3<Float>, 
                            upVector: SIMD3<Float> = SIMD3<Float>(0, 1, 0),
                            relativeTo referenceEntity: Entity?, 
                            forward: Entity.ForwardDirection = .negativeZ)

在这里,您可以看到如何借助更新新 ARKit 的 DeviceAnchor 的值来在 VisionOS 中实现

look(at:)
方法:

import SwiftUI
import RealityKit
import ARKit

extension simd_float4 {
    var xyz: simd_float3 {
        return simd_float3(x, y, z)
    }
}

@Observable class CameraAnchorUpdater {
    let session = ARKitSession()
    let worldTracking = WorldTrackingProvider()

    func runSession() async {
        Task {
            try? await session.run([worldTracking])
        }
    }
    func getMatrix() -> simd_float4x4 {
        guard let mtx = worldTracking
                         .queryDeviceAnchor(atTimestamp: CACurrentMediaTime())
        else { return .init() }
            
        return mtx.originFromAnchorTransform
    }
}

struct ContentView : View {
    var cau = CameraAnchorUpdater()
    let head = try! Entity.load(named: "head")
    
    func updatingSceneEventsWith(_ content: RealityViewContent) {
        _ = content.subscribe(to: SceneEvents.Update.self) { _ in
            let cameraPosition = cau.getMatrix().columns.3.xyz
            
            head.look(at: cameraPosition,
                    from: head.position,
              relativeTo: nil,
                 forward: .positiveZ)
            
            // X orientation's compensation (CCW)
            head.orientation *= .init(angle: .pi/10, axis: [1,0,0])
        }
    }
    
    var body: some View {
        RealityView { content in
            head.position.z = -3.0
            content.add(head)
            
            updatingSceneEventsWith(content)
        }
        .task {
            await cau.runSession()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.