我想将世界坐标转换为 RealityKit 实体的本地坐标。 根据 the docs,这应该可以使用
convert(position:from:)
来调用实体。
由于它没有按预期工作,我写了一个小测试项目。我使用了 Apple 的visionOS 沉浸式应用程序模板,并对其进行了轻微修改。这是我的沉浸式视图:
struct ImmersiveView: View {
var body: some View {
RealityView { content in
var defaultMaterial = UnlitMaterial()
defaultMaterial.color.tint = .brown
let mesh = MeshResource.generateBox(size: 1)
let boxEntity = ModelEntity(mesh: mesh, materials: [defaultMaterial])
let anchorEntity = AnchorEntity(world: SIMD3<Float>(0, 0, -4))
anchorEntity.addChild(boxEntity)
content.add(anchorEntity)
let coordinate = SIMD3<Float>(0.1, 0.2, 0.3)
let coordinateFrom = boxEntity.convert(position: coordinate, from: nil)
let coordinateTo = boxEntity.convert(position: coordinate, to: nil)
print("coordinateFrom: \(coordinateFrom)")
print("coordinateTo: \(coordinateTo)")
}
}
}
它包含一个在主窗口前面可见的框。盒子不在原点 (z = -4)。
出乎意料的是,
coordinateFrom
以及coordinateTo
等于coordinate
。我预计 coordinateFrom
会有所不同,因为盒子不在原点。我的一个朋友找到了解决方案:
显然,在坐标转换函数工作之前必须渲染视图。
这是演示转换的扩展代码:
struct ImmersiveView: View {
@State private var coordinateFrom = SIMD3<Float>(0, 0, 0)
@State private var coordinateTo = SIMD3<Float>(0, 0, 0)
@State private var anchorPosition = SIMD3<Float>(0, 0.0, -4)
var body: some View {
ZStack {
RealityView { content in
var defaultMaterial = UnlitMaterial()
defaultMaterial.color.tint = .brown
let mesh = MeshResource.generateBox(size: 1)
let boxEntity = ModelEntity(mesh: mesh, materials: [defaultMaterial])
boxEntity.name = "box"
let anchorEntity = AnchorEntity(world: anchorPosition)
anchorEntity.name = "anchor"
anchorEntity.addChild(boxEntity)
content.add(anchorEntity)
print("---- not yet rendered coords")
updateCoordinates(boxEntity: boxEntity)
}
update: { content in
if let anchorEntity = content.entities.first?.findEntity(named: "anchor") as? AnchorEntity {
anchorEntity.setPosition(anchorPosition, relativeTo: nil)
}
if let boxEntity = content.entities.first?.findEntity(named: "box") as? ModelEntity {
updateCoordinates(boxEntity: boxEntity)
}
}
VStack {
Text("Coordinate From: \(coordinateString(coordinateFrom))")
Text("Coordinate To: \(coordinateString(coordinateTo))")
Button(action: {
anchorPosition += SIMD3<Float>(Float.random(in: -1..<1), 0, 0)
}, label: { Text("Move") })
}
.padding()
.background(Color.black.opacity(0.5))
.cornerRadius(10)
.foregroundColor(.white)
}
}
private func updateCoordinates(boxEntity: ModelEntity) {
let coordinate = SIMD3<Float>(0.1, 0.2, 0.3)
let coordinateFrom = boxEntity.convert(position: coordinate, from: nil)
let coordinateTo = boxEntity.convert(position: coordinate, to: nil)
DispatchQueue.main.async {
self.coordinateFrom = coordinateFrom
self.coordinateTo = coordinateTo
}
print("coordinateFrom: \(coordinateFrom)")
print("coordinateTo: \(coordinateTo)")
}
private func coordinateString(_ coordinate: SIMD3<Float>) -> String {
String(format: "(%.2f, %.2f, %.2f)", coordinate.x, coordinate.y, coordinate.z)
}
}