6-6b 3D座標軸 — 設定「共享程式」
上節提到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()」加進來。
接下來以圓柱體(generateCylinder)畫軸線、圓錐體(generateCone)畫箭頭,最後再加上X, Y, Z文字標示(generateText)放在箭頭旁。
整個座標軸並未用到任何材質,RealityKit 會顯示特殊的紫色條紋,表示沒有材質。
此3D座標軸由10個模型個體組成,由於「座標原點」是根節點,最後只要回傳「座標原點」即可。所有個體的節點關係如下:

初學空間運算時,要特別注意以下幾點:
1. RealityKit 的座標方向,往螢幕右方是正X軸,往螢幕上方是正Y軸,垂直螢幕(往眼睛方向)是正Z軸。這又稱為右手坐標系(X=大拇指、Y=食指、Z=中指)。
2. 座標的長度單位是公制1米(以配合AR實景融合)
3. 每個個體(Entity)都有自己的區域座標,區域座標原點的初始位置由上層個體決定。
4. RealityView的座標原點由上層視圖決定,預設在螢幕中心點
5. RealityKit 預設幾何模型中,球體、立方體、圓柱體、圓錐體是以幾何中心為區域座標原點,文字(generateText)的區域座標原點在左下角。
例如在產出文字時,若字體大小為12點,將會變成12米,所以函式裡面將字體模型縮小為1/200 (0.005),變成6公分。
空間旋轉與simd_quatf()
x軸、y軸、z軸的軸線都由圓柱體構成,剛產出時,圓柱體中心對齊原點,高度沿Y軸方向,因此除了y軸直接可用之外,x軸與z軸需要經過旋轉才能到達正確位置。
旋轉的程式碼如下:
x軸.orientation = simd_quatf(angle: .pi / 2.0, axis: [0, 0, -1])
// 以及
z軸.orientation = simd_quatf(angle: .pi / 2.0, axis: [1, 0, 0])
前面提過每個個體(Entity)都有座標變換元件(Transform),因此共同的屬性有 position (座標位置)、scale (縮放或鏡像)、orientation (旋轉面向)以及 transform (座標變換),這些屬性在空間運算中非常重要。
此處設定旋轉面向時,用到一個新物件 simd_quatf,這個物件是特別用來加速CPU計算的資料結構,對空間運算很有用,下一節(補充18)會詳細介紹。
上面第一行程式碼,是要依著-Z軸逆時針轉90°(弳度0.5π),等同依+Z軸順時針轉90°,將y軸軸線轉成x軸。上面 simd_quatf 的參數 axis: [0, 0, -1],axis 是軸心、轉軸的意思,參數值[0, 0, -1]是向量(而不是點座標),即-Z軸方向。
有了「座標軸()」共享函式,主程式就簡單多了,將以下幾行貼在一個新增頁面6-6b(參考下圖):
// 6-6b 3D座標系統
// Created by Heman Lu on 2025/02/03
// Test Environment: iMac 2019 (macOS 15.3) + Swift Playground 4.6
import SwiftUI
import RealityKit
struct 顯示座標軸: View {
var body: some View {
RealityView { 內容 in
內容.add(座標軸()) // 座標軸() 放在共享程式區
}.realityViewCameraControls(.orbit)
}
}
import PlaygroundSupport
PlaygroundPage.current.setLiveView(顯示座標軸())
執行結果如下:

確認程式可順利執行之後,還要進一步將共享的目錄與檔案重新命名,以後找尋比較容易。

只要出現在共享區的目錄與檔案,都會自動共享,重新命名也不影響,因此,未來我們可以給每個共享程式新增一個 .swift 檔案。
💡註解
- 注意Swift程式裡面,任何命名都不能以半形數字開頭,也就是說,不能取名為「3D座標軸()」,只能叫「座標軸()」或「座標軸3D()」。此外,名稱內(任何位置)也不能包含半形標點符號,唯一例外是底線 “_” (underscore)。
- simd_quatf 是個專業術語縮寫(用 C 語言的命名習慣),對高中生來說可能不容易理解,但又非常重要,下一節會特別介紹。
- simd 代表 “Single Instruction Multiple Data”,是一種CPU硬體指令,可用一個指令並行處理多筆資料(正常一個CPU指令只能處理一筆資料,如整數運算2*3,而 simd 可一次處理多筆資料運算)。
- quat 代表四元數(quaternion),例如(0.707, 0.0, 0.0, -0.707)。
- f 代表浮點數(floating-point),通常是32位元的實數,如0.707。
- 所以 simd_quatf 表示「32位元浮點四元數的並行運算指令」,常用於3D空間的旋轉。可參考交大周志成老師「線代啟示錄」或維基百科:四元數與空間旋轉。
- 對Swift Playground 的 App模式來說,程式碼同樣可分散在不同 .swift 檔案(放在左側欄「程式碼」區),但所有 .swift 檔案視為同一個模組,所以並不需要宣告為 public 即可互通。
- 作業:請將「座標軸()」加入上一節範例程式6-6a,執行後轉動畫面檢視圓球位置。
- 作業:請將「座標軸()」參數改為 x/y/z 軸可不同長度,例如「座標軸(x: 1.5)」。