目前在空間運算當中,沉浸式的觀賞照片或者影片,是一個全新體驗空間運算的特別功能之一。這個單元來討論如何將照片置入空間當中。
首先,先準備一張360度的照片,匯入到專案:
讀取這張照片:
struct ImmersiveView: View {
@State var textureRequest: AnyCancellable?
var body: some View {
RealityView { content in
let rootEntity = Entity()
textureRequest = TextureResource.loadAsync(named: "photo").sink { (error) in
print(error)
} receiveValue: { (texture) in
var material = UnlitMaterial()
material.color = .init(texture: .init(texture))
rootEntity.components.set(ModelComponent(
mesh: .generateSphere(radius: 1E3),
materials: [material]
))
rootEntity.scale *= .init(x: -1, y: 1, z: 1)
rootEntity.transform.translation += SIMD3<Float>(0.0, 1.0, 0.0)
}
content.add(rootEntity)
}
}
}
程式碼逐行解說:
textureRequest = TextureResource.loadAsync(named: "photo"):使用非同步方式讀取照片名稱為photo的資源,並將其分配給textureRequest。TextureResource.loadAsync方法返回一個 AnyPublisher,可以被sink訂閱。
如果讀取成功,則會使用receiveValue這個call back回傳結果。
var material = UnlitMaterial():新增一個未上色的材質,且該材質不會受到燈光影響。
material.color = .init(texture: .init(texture)):將讀取到的資源初始化給顏色的屬性。
rootEntity.components.set:新增了一個半徑為1E3的球體,並且將材質設定剛剛所建立的material。
rootEntity.scale = .init(x: -1, y: 1, z: 1):將rootEntity的縮放沿x軸翻轉,使得球體的內部朝外。
rootEntity.transform.translation += SIMD3(0.0, 1.0, 0.0):將rootEntity向上移動1。
回到程式進入點,在ImmersiveSpace加入屬性immersionStyle:
ImmersiveSpace(id: "ImmersiveSpace") {
ImmersiveView()
}
.immersionStyle(selection: .constant(.progressive), in: .progressive)
如果要修改為360環景,則修改immersionStyle屬性為full:
ImmersiveSpace(id: "ImmersiveSpace") {
ImmersiveView()
}
.immersionStyle(selection: .constant(.full), in: .full)
開啟App之後:
打開開關,圖片就會放置於整個空間了:
完整程式碼。
程式進入點:
@main
struct TestVisionApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
ImmersiveSpace(id: "ImmersiveSpace") {
ImmersiveView()
}
.immersionStyle(selection: .constant(.progressive), in: .progressive)
}
}
視窗View:
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
@State private var showImmersiveSpace = false
@Environment(\.openImmersiveSpace) var openImmersiveSpace
@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
var body: some View {
VStack {
Toggle("Show ImmersiveSpace", isOn: $showImmersiveSpace)
.font(.title)
.frame(width: 360)
.padding(24)
.glassBackgroundEffect()
}
.padding()
.onChange(of: showImmersiveSpace) { _, newValue in
Task {
if newValue {
await openImmersiveSpace(id: "ImmersiveSpace")
}
else {
await dismissImmersiveSpace()
}
}
}
}
}
場景View:
import SwiftUI
import RealityKit
import Combine
struct ImmersiveView: View {
@State var textureRequest: AnyCancellable?
var body: some View {
RealityView { content in
let rootEntity = Entity()
textureRequest = TextureResource.loadAsync(named: "photo").sink { (error) in
print(error)
} receiveValue: { (texture) in
var material = UnlitMaterial()
material.color = .init(texture: .init(texture))
rootEntity.components.set(ModelComponent(
mesh: .generateSphere(radius: 1E3),
materials: [material]
))
rootEntity.scale *= .init(x: -1, y: 1, z: 1)
rootEntity.transform.translation += SIMD3<Float>(0.0, 1.0, 0.0)
}
content.add(rootEntity)
}
}
}
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day29 [完]