对于 SCNNodes,我们有
SCNBillboardConstraint
,那么有什么方法可以将此约束应用于实体(当使用 RealityKit 而不是 SceneKit 时),以便实体在设备移动时始终面向相机?
使用 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 版本有一个附加参数,称为
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()
}
}
}