上節提到RealityKit 預設的幾何模型只有6種:包括3D文字、立方體、球體、平面、圓錐體、圓柱體等,均使用 MeshResource 的類型方法產出。
雖然預設模型種類不多,但加以組合還是可以製作不少物件,本節就利用3D文字、圓錐體、圓柱體來製作一個「3D座標軸」,以便在後續程式中當作虛擬空間的參考座標。
我們要將「3D座標軸」做成「共享程式」,這樣以後每個頁面都可用到,避免程式碼一再重複。怎麼做呢?在電子書模式(playgroudbook)下,只要將下面寫好的「座標軸()」函式,剪貼到左側欄「原始碼」之下的 “SharedCode.swift” 裡面即可。
搬移到共享程式唯一需要更改的地方,是函式必須宣告為 “public” (公開),如果沒有加 public,主程式會出現以下錯誤:”Cannot find ‘座標軸’ in scope” (有效範圍內找不到「座標軸」名稱)
這是因為主程式與共享程式現在位於不同模組,預設是不能互通的,只有宣告為 “public” 的函式、變數或物件,才能讓別的模組取用。
共享的「座標軸()」程式碼如下:
// 6-6b 3D座標系統
// Created by Heman Lu on 2025/02/03
// Test Environment: iMac 2019 (macOS 15.3) + Swift Playground 4.6.1
import RealityKit
public func 座標軸(_ 軸長: Float = 1.0) -> ModelEntity {
let 原點 = MeshResource.generateSphere(radius: 0.0)
let 軸線 = MeshResource.generateCylinder(height: 軸長 * 2.0, radius: 軸長 * 0.001)
let 箭頭 = MeshResource.generateCone(height: 軸長 * 0.07, radius: 軸長 * 0.01)
let 座標原點 = ModelEntity(mesh: 原點)
let y軸 = ModelEntity(mesh: 軸線)
let 箭頭y = ModelEntity(mesh: 箭頭)
箭頭y.position.y = 軸長
y軸.addChild(箭頭y)
座標原點.addChild(y軸)
let x軸 = ModelEntity(mesh: 軸線)
let 箭頭x = ModelEntity(mesh: 箭頭)
箭頭x.position.y = 軸長
x軸.addChild(箭頭x)
x軸.orientation = simd_quatf(angle: .pi / 2.0, axis: [0, 0, -1])
let z軸 = ModelEntity(mesh: 軸線)
let 箭頭z = ModelEntity(mesh: 箭頭)
箭頭z.position.y = 軸長
z軸.addChild(箭頭z)
z軸.orientation = simd_quatf(angle: .pi / 2.0, axis: [1, 0, 0])
let 字體比例 = 軸長 * 0.005
let y字 = ModelEntity(mesh: .generateText("Y"))
y字.scale = [字體比例, 字體比例, 字體比例]
y字.position.y = 軸長
座標原點.addChild(y字)
let x字 = ModelEntity(mesh: .generateText("X"))
x字.scale = [字體比例, 字體比例, 字體比例]
x字.position.x = 軸長
座標原點.addChild(x字)
座標原點.addChild(x軸)
let z字 = ModelEntity(mesh: .generateText("Z"))
z字.scale = [字體比例, 字體比例, 字體比例]
z字.position.z = 軸長
座標原點.addChild(z字)
座標原點.addChild(z軸)
return 座標原點
}
注意第一行 import RealityKit,每個共享程式還是要導入所需框架。
「座標軸()」會以模型個體(ModelEntity)的類型傳回一個做好的X/Y/Z座標系統,以後要用時,只要呼叫「座標軸()」並加入「內容」即可:
內容.add(座標軸()) // 預設XYZ軸長±1.0米
// 或
內容.add(座標軸(2.5)) // XYZ軸長±2.5米
實際做法,我們先產出一個隱藏的(半徑=0)小球模型「座標原點」,當作整個座標系的原點,也是所有個體的根節點,其他個體用「座標原點.addChild()」加進來。