Threejs的三維座標系

calmound發表於2024-11-26

在三維空間中,所有的物體和相機都需要基於一個統一的座標系來進行定位和操作。理解座標系的基本概念,對於建立穩定、準確的三維效果至關重要。

基礎

Three.js 採用的是右手座標系,這意味著如果你將右手的三個手指伸直,分別指向 X、Y 和 Z 軸的方向,你的拇指指向的方向即為 X 軸,食指指向的方向即為 Y 軸,而中指指向的方向則是 Z 軸的正方向。

  • X 軸:表示水平方向,正方向指向右側。
  • Y 軸:表示垂直方向,正方向指向上方。
  • Z 軸:表示深度方向,正方向指向觀察者外,負方向指向觀察者內。
    這一座標系為我們提供了一個標準化的方式來描述三維空間中的物體位置、旋轉和縮放。
    file

座標軸的作用

在 Three.js 中,座標軸用於表示和定位物體。每個物體都有一個 position 屬性,這個屬性決定了物體在三維空間中的位置。透過調整 position 屬性的 X、Y 和 Z 值,我們可以在三維空間中自由移動物體。

此外,座標軸還有助於理解物體的旋轉和縮放。透過旋轉和縮放矩陣,我們可以對物體進行旋轉、縮放等操作,而這些操作的基礎就是 Three.js 中的座標系。

Three.js 座標系中的各個概念

世界座標系與區域性座標系

在 Three.js 中,座標系分為世界座標系和區域性座標系。它們分別用於描述物體在全域性場景中的位置與物體相對於自身的變換。

世界座標系

世界座標系(World Coordinate System)是整個 Three.js 場景的全域性座標系統,用於統一描述場景中所有物體的位置、旋轉和縮放。它是絕對的、唯一的,類似於地圖中的全球座標,所有的物體都透過相對於這個全域性座標系的數值來定位。

特點

  • 固定原點:世界座標系的原點 (0, 0, 0) 是整個場景的基準點。
  • 統一參照系:無論物體如何移動、旋轉或縮放,世界座標系始終不變。
  • 絕對性:物體的世界座標描述的是它在整個場景中的絕對位置和狀態。

用途

  • 描述物體在場景中的絕對位置。
  • 用於相機、燈光等全域性性的設定。
  • 渲染引擎根據物體的世界座標來決定最終的顯示效果。
  • 建立一個物體並設定其位置:
const cube = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
cube.position.set(5, 3, -2); // 設定物體在世界座標系中的位置 scene.add(cube);`;

在這個例子中,立方體 cube 的位置為 (5, 3, -2),這表示它相對於場景的原點 (0, 0, 0) 在 X 方向移動了 5,Y 方向移動了 3,Z 方向移動了 -2。

區域性座標系

區域性座標系(Local Coordinate System)是物體自身的座標系統,每個物體都有自己的區域性座標系,用於描述其內部的座標參照。區域性座標系的原點通常位於物體的中心(除非模型本身定義了不同的原點)。

特點

  • 動態原點:物體的區域性座標系原點始終跟隨物體的位置和旋轉。
  • 相對性:區域性座標系中的變換是相對於物體本身的,而不是世界座標系。
  • 層級關係:區域性座標系會受到父物體座標系的影響。

用途

  • 用於物體的自定義變換(如區域性旋轉或區域性平移)。
  • 在複雜的層級場景中,子物體相對於父物體的位置和方向可以透過區域性座標系來定義。
  • 在動畫和互動中,對物體的區域性座標系進行操作更靈活。
  • 在區域性座標系中,旋轉物體:
const cube = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
cube.rotation.set(Math.PI / 4, 0, 0); // 繞區域性 X 軸旋轉 45 度
scene.add(cube);

在這裡,立方體 cube 繞自身的區域性 X 軸旋轉,而不是繞場景的世界 X 軸旋轉。

物體變換:位置、旋轉與縮放

Three.js 中的物體變換通常由三個基本操作構成:位置、旋轉和縮放。

位置(Position):物體的位置由其在三維空間中的座標來表示。透過修改物體的 .position 屬性,可以改變物體在場景中的位置。

object.position.set(10, 5, -3);

旋轉(Rotation):旋轉是指物體圍繞某個軸進行旋轉。Three.js 使用 Euler 角和四元數兩種方式來描述物體的旋轉。Euler 角透過三個角度來表示物體的旋轉,而四元數則避免了萬向鎖問題。你可以使用 .rotation 屬性來設定物體的旋轉,或者使用 .quaternion 屬性來直接應用四元數旋轉。

object.rotation.set(Math.PI / 2, 0, 0); // 旋轉 90 度

縮放(Scale):縮放決定物體的大小。Three.js 中的 .scale 屬性允許你分別調整 X、Y 和 Z 軸方向上的縮放比例。

object.scale.set(2, 2, 2); // 將物體縮放到原來的 2 倍大小

檢視座標系與世界座標系的關係

相機檢視座標系是相對於相機的位置和方向而言的,與世界座標系的關係透過相機的投影矩陣來轉換。當我們渲染一個物體時,Three.js 會將物體的世界座標轉換為相機座標系中的座標,再透過投影矩陣將其對映到螢幕座標系中。

透過這種方式,物體的實際位置、旋轉和縮放資訊最終影響它在螢幕上的顯示。

座標系在 Three.js 渲染流程中的應用

渲染時座標系的轉換

Three.js 渲染時涉及多個座標系的轉換過程:

從模型座標系到世界座標系:物體在其區域性座標系中的位置、旋轉和縮放應用後,轉換到世界座標系。
從世界座標系到相機座標系:物體的世界座標經過相機的視角變換後,得到相對於相機的座標。
從相機座標系到螢幕座標系:透過投影矩陣將物體從三維座標對映到二維螢幕上,最終顯示在瀏覽器中。

常見座標系變換的示例

舉個例子,假設我們有一個物體,並希望將其從世界座標系轉換到螢幕座標系,可以透過以下步驟:

const vector = new THREE.Vector3(10, 5, -10); // 物體在世界座標系中的位置
vector.project(camera); // 將物體位置從世界座標系轉換為相機座標系

這段程式碼演示瞭如何透過相機將物體的世界座標轉換為螢幕座標,便於後續的渲染和互動操作。

座標系除錯與工具

座標軸幫助工具
在 Three.js 中,AxesHelper 和 GridHelper 是兩個常用的除錯工具,它們分別用於顯示三維座標軸和網格。

const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper); // 在場景中新增座標軸幫助器

透過這些工具,我們可以直觀地看到物體的座標軸,幫助我們理解物體在三維空間中的位置和方向。

座標變換工具

Three.js 提供了 applyMatrix4() 方法,可以幫助我們對物體進行手動的座標變換。透過這種方法,我們可以對物體應用平移、旋轉和縮放等操作。

const matrix = new THREE.Matrix4();
matrix.makeTranslation(10, 0, 0); // 建立一個平移矩陣
object.applyMatrix4(matrix); // 將矩陣應用到物體

座標系常見問題與解決方法

萬向鎖問題

在使用 Euler 角進行旋轉時,可能會遇到萬向鎖問題,即某些旋轉軸會因為連續旋轉而出現錯誤的行為。為了解決這個問題,Three.js 提供了四元數(Quaternion)來避免萬向鎖。

object.rotation.setFromQuaternion(
  new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 2, 0, 0))
);

座標系誤差與漂移

在大規模場景中,浮動精度可能導致座標系出現漂移現象。通常可以透過最佳化計算精度和使用大範圍座標系來解決這些問題。

相關文章