Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Basis

用於表示 3D 旋轉與縮放的 3×3 矩陣。

說明

The Basis built-in Variant type is a 3×3 matrix used to represent 3D rotation, scale, and shear. It is frequently used within a Transform3D.

A Basis is composed by 3 axis vectors, each representing a column of the matrix: x, y, and z. The length of each axis (Vector3.length()) influences the basis's scale, while the direction of all axes influence the rotation. Usually, these axes are perpendicular to one another. However, when you rotate any axis individually, the basis becomes sheared. Applying a sheared basis to a 3D model will make the model appear distorted.

A Basis is:

  • Orthogonal if its axes are perpendicular to each other.

  • Normalized if the length of every axis is 1.0.

  • Uniform if all axes share the same length (see get_scale()).

  • Orthonormal if it is both orthogonal and normalized, which allows it to only represent rotations (see orthonormalized()).

  • Conformal if it is both orthogonal and uniform, which ensures it is not distorted.

For a general introduction, see the Matrices and transforms tutorial.

Note: Godot uses a right-handed coordinate system, which is a common standard. For directions, the convention for built-in types like Camera3D is for -Z to point forward (+X is right, +Y is up, and +Z is back). Other objects may use different direction conventions. For more information, see the 3D asset direction conventions tutorial.

Note: The basis matrices are exposed as column-major order, which is the same as OpenGL. However, they are stored internally in row-major order, which is the same as DirectX.

Note: In a boolean context, a basis will evaluate to false if it's equal to IDENTITY. Otherwise, a basis will always evaluate to true.

備註

使用 C# 操作此 API 時有顯著差異,詳見 C# API 與 GDScript 的不同

教學

屬性

Vector3

x

Vector3(1, 0, 0)

Vector3

y

Vector3(0, 1, 0)

Vector3

z

Vector3(0, 0, 1)

建構子

Basis

Basis()

Basis

Basis(from: Basis)

Basis

Basis(axis: Vector3, angle: float)

Basis

Basis(from: Quaternion)

Basis

Basis(x_axis: Vector3, y_axis: Vector3, z_axis: Vector3)

方法

float

determinant() const

Basis

from_euler(euler: Vector3, order: int = 2) static

Basis

from_scale(scale: Vector3) static

Vector3

get_euler(order: int = 2) const

Quaternion

get_rotation_quaternion() const

Vector3

get_scale() const

Basis

inverse() const

bool

is_conformal() const

bool

is_equal_approx(b: Basis) const

bool

is_finite() const

bool

is_orthonormal() const

Basis

looking_at(target: Vector3, up: Vector3 = Vector3(0, 1, 0), use_model_front: bool = false) static

Basis

orthonormalized() const

Basis

rotated(axis: Vector3, angle: float) const

Basis

scaled(scale: Vector3) const

Basis

scaled_local(scale: Vector3) const

Basis

slerp(to: Basis, weight: float) const

float

tdotx(with: Vector3) const

float

tdoty(with: Vector3) const

float

tdotz(with: Vector3) const

Basis

transposed() const

運算子

bool

operator !=(right: Basis)

Basis

operator *(right: Basis)

Vector3

operator *(right: Vector3)

Basis

operator *(right: float)

Basis

operator *(right: int)

Basis

operator /(right: float)

Basis

operator /(right: int)

bool

operator ==(right: Basis)

Vector3

operator [](index: int)


常數

IDENTITY = Basis(1, 0, 0, 0, 1, 0, 0, 0, 1) 🔗

單位 Basis。此基底為正交正規,無旋轉、無斜切,縮放為 Vector3.ONE。因此:

var basis = Basis.IDENTITY
print("| X | Y | Z")
print("| %.f | %.f | %.f" % [basis.x.x, basis.y.x, basis.z.x])
print("| %.f | %.f | %.f" % [basis.x.y, basis.y.y, basis.z.y])
print("| %.f | %.f | %.f" % [basis.x.z, basis.y.z, basis.z.z])
# 印出:
# | X | Y | Z
# | 1 | 0 | 0
# | 0 | 1 | 0
# | 0 | 0 | 1

若將任何 Vector3Basis 與此常數相乘,結果不會產生任何變換。

注意: 在 GDScript 中,此常數等同於不帶參數建構 Basis,可使程式碼更易讀,並與 C# 行為一致。

FLIP_X = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1) 🔗

任意基底右乘 FLIP_X 時,會反轉 x 軸(X 欄)的所有分量。

FLIP_X 左乘任意基底時,會反轉所有軸的 Vector3.x 分量(X 列)。

FLIP_Y = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1) 🔗

任意基底右乘 FLIP_Y 時,會反轉 y 軸(Y 欄)的所有分量。

FLIP_Y 左乘任意基底時,會反轉所有軸的 Vector3.y 分量(Y 列)。

FLIP_Z = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1) 🔗

任意基底右乘 FLIP_Z 時,會反轉 z 軸(Z 欄)的所有分量。

FLIP_Z 左乘任意基底時,會反轉所有軸的 Vector3.z 分量(Z 列)。


屬性說明

Vector3 x = Vector3(1, 0, 0) 🔗

基底的 X 軸暨矩陣第 0 欄。

在單位基底中,此向量指向右方(Vector3.RIGHT)。


Vector3 y = Vector3(0, 1, 0) 🔗

基底的 Y 軸暨矩陣第 1 欄。

在單位基底中,此向量指向上方(Vector3.UP)。


Vector3 z = Vector3(0, 0, 1) 🔗

基底的 Z 軸暨矩陣第 2 欄。

在單位基底中,此向量指向後方(Vector3.BACK)。


建構子說明

Basis Basis() 🔗

建構一個與 IDENTITY 完全相同的 Basis

注意: 在 C# 中,這會建構一個所有分量皆為 Vector3.ZEROBasis


Basis Basis(from: Basis)

建構指定 Basis 的複本。


Basis Basis(axis: Vector3, angle: float)

建構一個僅表示旋轉的 Basis,其旋轉為:繞 axis 轉動 angle 弧度。 axis 必須是正規化向量。

注意: 這等同於對 IDENTITY 呼叫 rotated()。若需同時指定多個軸向角度,請改用 from_euler()


Basis Basis(from: Quaternion)

根據指定的 Quaternion 建構一個僅表示旋轉的 Basis

注意: 四元數 儲存旋轉資訊,不含縮放,因此由 Basis 轉換為 Quaternion 後不一定能完整還原。


Basis Basis(x_axis: Vector3, y_axis: Vector3, z_axis: Vector3)

使用三個軸向量建構 Basis;這三個向量即為矩陣的三個欄。


方法說明

float determinant() const 🔗

Returns the determinant of this basis's matrix. For advanced math, this number can be used to determine a few attributes:

  • If the determinant is exactly 0.0, the basis is not invertible (see inverse()).

  • If the determinant is a negative number, the basis represents a negative scale.

Note: If the basis's scale is the same for every axis, its determinant is always that scale by the power of 3.


Basis from_euler(euler: Vector3, order: int = 2) static 🔗

Constructs a new Basis that only represents rotation from the given Vector3 of Euler angles, in radians.

  • The Vector3.x should contain the angle around the x axis (pitch);

  • The Vector3.y should contain the angle around the y axis (yaw);

  • The Vector3.z should contain the angle around the z axis (roll).

# Creates a Basis whose z axis points down.
var my_basis = Basis.from_euler(Vector3(TAU / 4, 0, 0))

print(my_basis.z) # Prints (0.0, -1.0, 0.0)

The order of each consecutive rotation can be changed with order (see EulerOrder constants). In Godot, Euler angles always use intrinsic order. By default, the intrinsic YXZ convention is used (@GlobalScope.EULER_ORDER_YXZ): the basis rotates first around the local Y axis (yaw), then local X (pitch), and lastly local Z (roll). When using the opposite method get_euler() to decompose a rotation, this order is reversed.


Basis from_scale(scale: Vector3) static 🔗

以指定的 scale 向量建立新的 Basis,僅含縮放,不含旋轉與斜切。

var my_basis = Basis.from_scale(Vector3(2, 4, 8))
print(my_basis.x) # 印出 (2.0, 0.0, 0.0)
print(my_basis.y) # 印出 (0.0, 4.0, 0.0)
print(my_basis.z) # 印出 (0.0, 0.0, 8.0)

注意: 線性代數中,該矩陣亦稱為對角矩陣


Vector3 get_euler(order: int = 2) const 🔗

Returns this basis's rotation as a Vector3 of Euler angles, in radians. For the returned value:

  • The Vector3.x contains the angle around the x axis (pitch);

  • The Vector3.y contains the angle around the y axis (yaw);

  • The Vector3.z contains the angle around the z axis (roll).

The order of each consecutive rotation can be changed with order (see EulerOrder constants). In Godot, Euler angles always use intrinsic order. By default, the intrinsic YXZ convention is used (@GlobalScope.EULER_ORDER_YXZ): since we are decomposing, local Z (roll) is calculated first, then local X (pitch), and lastly local Y (yaw). When using the opposite method from_euler() to compose a rotation, this order is reversed.

Note: For this method to return correctly, the basis needs to be orthonormal (see orthonormalized()).

Note: Euler angles are much more intuitive but are not suitable for 3D math. Because of this, consider using the get_rotation_quaternion() method instead, which returns a Quaternion.

Note: In the Inspector dock, a basis's rotation is often displayed in Euler angles (in degrees), as is the case with the Node3D.rotation property.


Quaternion get_rotation_quaternion() const 🔗

Quaternion 形式回傳此基底的旋轉。

注意: 四元數較適用於 3D 計算,但不直觀;若用於 UI 顯示,可改用 get_euler() 取得歐拉角。


Vector3 get_scale() const 🔗

Vector3 回傳此基底各軸向量的長度。若基底無斜切,此值即為縮放倍率,並不受旋轉影響。

var my_basis = Basis(
    Vector3(2, 0, 0),
    Vector3(0, 4, 0),
    Vector3(0, 0, 8)
)
# 不論如何旋轉,縮放皆會保持。
my_basis = my_basis.rotated(Vector3.UP, TAU / 2)
my_basis = my_basis.rotated(Vector3.RIGHT, TAU / 4)
print(my_basis.get_scale()) # 印出 (2.0, 4.0, 8.0)

注意:determinant() 為負,縮放亦為負值。


Basis inverse() const 🔗

傳回此基矩陣的逆矩陣


bool is_conformal() const 🔗

若此基底為共形(同時 正交等比例),則回傳 true。在物理運算中檢查此性質特別實用。


bool is_equal_approx(b: Basis) const 🔗

如果該基和 b 近似相等,則返回 true,判斷方法是在每個向量分量上呼叫 @GlobalScope.is_equal_approx()


bool is_finite() const 🔗

如果該基是有限的,則返回 true,判斷方法是在每個向量分量上呼叫 @GlobalScope.is_finite()


bool is_orthonormal() const 🔗

Returns true if this basis is orthonormal. An orthonormal basis is both orthogonal (the axes are perpendicular to each other) and normalized (the length of every axis is 1.0). This method can be especially useful during physics calculations.


Basis looking_at(target: Vector3, up: Vector3 = Vector3(0, 1, 0), use_model_front: bool = false) static 🔗

建立新的 Basis,其旋轉使得前向軸 (-Z) 指向 target 位置。

預設情況下,-Z 為前向(攝影機前),+X 為右;若 use_model_front 設為 true,則改以 +Z 為前向(模型前),+X 為左,並同樣指向 target

上軸 (+Y) 會盡量貼近 up 向量,同時保持與前向軸垂直。回傳的基底已進行 正交正規化(參閱 orthonormalized())。

targetup 皆不得為 Vector3.ZERO,且兩向量不應共線,否則可能導致繞本地 Z 軸的非預期旋轉。


Basis orthonormalized() const 🔗

回傳此基底的正交正規化版本。正交正規基底同時 正交(三軸互相垂直)且 正規化(每軸長度為 1.0),因此只能表示純旋轉。

在不斷旋轉的基底上,定期呼叫此方法可避免累積的浮點誤差:

# 每幀旋轉此 Node3D
func _process(delta):
    basis = basis.rotated(Vector3.UP, TAU * delta)
    basis = basis.rotated(Vector3.RIGHT, TAU * delta)
    basis = basis.orthonormalized()

Basis rotated(axis: Vector3, angle: float) const 🔗

回傳繞 axis 旋轉 angle 弧度後的基底副本。

axis 必須為正規化向量(參閱 Vector3.normalized())。若 angle 為正,則以左手方向(逆時針)旋轉。

var my_basis = Basis.IDENTITY
var angle = TAU / 2
my_basis = my_basis.rotated(Vector3.UP, angle)    # 繞上軸(偏航)
my_basis = my_basis.rotated(Vector3.RIGHT, angle) # 繞右軸(俯仰)
my_basis = my_basis.rotated(Vector3.BACK, angle)  # 繞後軸(翻滾)

Basis scaled(scale: Vector3) const 🔗

回傳將此基底各軸向量分量分別乘以 scale 對應分量後的結果。

矩陣的列會乘上 scale,此動作屬全域縮放(相對於父節點)。

var my_basis = Basis(
    Vector3(1, 1, 1),
    Vector3(2, 2, 2),
    Vector3(3, 3, 3)
)
my_basis = my_basis.scaled(Vector3(0, 2, -2))
print(my_basis.x) # 印出 (0.0, 2.0, -2.0)
print(my_basis.y) # 印出 (0.0, 4.0, -4.0)
print(my_basis.z) # 印出 (0.0, 6.0, -6.0)

Basis scaled_local(scale: Vector3) const 🔗

Returns this basis with each axis scaled by the corresponding component in the given scale.

The basis matrix's columns are multiplied by scale's components. This operation is a local scale (relative to self).

var my_basis = Basis(
    Vector3(1, 1, 1),
    Vector3(2, 2, 2),
    Vector3(3, 3, 3)
)
my_basis = my_basis.scaled_local(Vector3(0, 2, -2))

print(my_basis.x) # Prints (0.0, 0.0, 0.0)
print(my_basis.y) # Prints (4.0, 4.0, 4.0)
print(my_basis.z) # Prints (-6.0, -6.0, -6.0)

Basis slerp(to: Basis, weight: float) const 🔗

以球面線性插值(SLERP)方式,依 weight 在此基底與 to 之間插值。兩者都應只表示旋轉。

範例: 使用 Tween 在一段時間內平滑地將 Node3D 旋轉到目標基底:

var start_basis = Basis.IDENTITY
var target_basis = Basis.IDENTITY.rotated(Vector3.UP, TAU / 2)

func _ready():
    create_tween().tween_method(interpolate, 0.0, 1.0, 5.0).set_trans(Tween.TRANS_EXPO)

func interpolate(weight):
    basis = start_basis.slerp(target_basis, weight)

float tdotx(with: Vector3) const 🔗

回傳 withx 軸之間的轉置點積(參閱 transposed())。

等同於 basis.x.dot(vector)


float tdoty(with: Vector3) const 🔗

回傳 withy 軸之間的轉置點積(參閱 transposed())。

等同於 basis.y.dot(vector)


float tdotz(with: Vector3) const 🔗

回傳 withz 軸之間的轉置點積(參閱 transposed())。

等同於 basis.z.dot(vector)


Basis transposed() const 🔗

回傳此基底的轉置矩陣,將原本的欄轉為列、列轉為欄。

var my_basis = Basis(
    Vector3(1, 2, 3),
    Vector3(4, 5, 6),
    Vector3(7, 8, 9)
)
my_basis = my_basis.transposed()
print(my_basis.x) # 印出 (1.0, 4.0, 7.0)
print(my_basis.y) # 印出 (2.0, 5.0, 8.0)
print(my_basis.z) # 印出 (3.0, 6.0, 9.0)

運算子說明

bool operator !=(right: Basis) 🔗

若兩個 Basis 矩陣的對應分量不相等,回傳 true

注意: 由於浮點精度誤差,建議改用 is_equal_approx() 進行比較以提升可靠性。


Basis operator *(right: Basis) 🔗

right 基底乘以此基底(右乘)。

此運算與父子 Node3D 之間的變換相同。


Vector3 operator *(right: Vector3) 🔗

將向量 right 乘以此基底並回傳 Vector3 結果。

# 可交換 X/Z 並將縮放加倍的 Basis
var my_basis = Basis(Vector3(0, 2, 0), Vector3(2, 0, 0), Vector3(0, 0, 2))
print(my_basis * Vector3(1, 2, 3)) # 印出 (4.0, 2.0, 6.0)

Basis operator *(right: float) 🔗

將此 Basis 所有分量乘以指定 float,等比例改變三軸尺寸。


Basis operator *(right: int) 🔗

將此 Basis 所有分量乘以指定 int,等比例改變三軸尺寸。


Basis operator /(right: float) 🔗

將此 Basis 所有分量除以指定 float,等比例改變三軸尺寸。


Basis operator /(right: int) 🔗

將此 Basis 所有分量除以指定 int,等比例改變三軸尺寸。


bool operator ==(right: Basis) 🔗

若兩個 Basis 矩陣的對應分量完全相同,回傳 true

注意: 由於浮點精度誤差,建議改用 is_equal_approx() 進行比較以提升可靠性。


Vector3 operator [](index: int) 🔗

透過索引存取此基底的各軸(欄)。索引 0 等同 x1 等同 y2 等同 z

注意: 在 C++ 中,該運算子會存取矩陣的列,而欄;若要與腳本語言行為一致,請使用 set_columnget_column